| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- <template>
- <div style="position: relative">
- <div id="bmap"></div>
- <ShipSearch
- class="ship-search z20"
- :searchapi="isSafety ? 'searchSafetyShipSelect' : 'searchShipSelect'"
- v-model="shipStr"
- @selectItem="selectShip($event, 1)"
- style="position: absolute; top: 40px; right: 524px"
- ></ShipSearch>
- <NumberVue
- class="z20"
- v-if="this.$store.state.currentTabText != '环境中心'"
- :data="this.$store.state.numbers"
- style="position: absolute; top: 0; left: 0"
- ></NumberVue>
- <SafetyModule
- class="z20"
- v-if="this.$store.state.currentTabText == '运输安全管理中心'"
- style="position: absolute; top: 24px; right: 34px"
- ></SafetyModule>
- <IntelligentModule
- class="z20"
- v-if="this.$store.state.currentTabText == '智能交易中心'"
- style="position: absolute; top: 24px; right: 34px"
- ></IntelligentModule>
- <EnvironmentalModule
- class="z20"
- v-if="this.$store.state.currentTabText == '环境中心'"
- style="position: absolute; top: 24px; right: 34px"
- ></EnvironmentalModule>
- <Warning
- class="z20"
- v-if="this.$store.state.currentTabText == '环境中心'"
- style="position: absolute; top: 40px; left: 20px; right: 744px"
- ></Warning>
- <div class="mask"></div>
- </div>
- </template>
- <script>
- import ShipSearch from "comps/ShipSearch.vue";
- import router from "router/index";
- import store from "store/index";
- import api from "apis/fetch";
- import { ref, onMounted, watch } from "vue";
- import { useRoute } from "vue-router";
- export default {
- components: {
- ShipSearch,
- },
- setup() {
- const bmap = ref({});
- let shipStr = ref("");
- const route = useRoute();
- // 初始化地图
- function initMap() {
- bmap.value = new BMapGL.Map("bmap", {
- minZoom: 5,
- maxZoom: 14,
- });
- bmap.value.setMapStyleV2({
- styleId: "fa3f2f79d64ac87e2683cfa762891cb5",
- });
- bmap.value.centerAndZoom(new BMapGL.Point(120.688612, 31.975529), 11);
- bmap.value.enableScrollWheelZoom(true);
- bmap.value.addEventListener("zoomend", changeZoomByLevel);
- }
- let cacheLevel = ref(0);
- let prevLevel = ref(0);
- // 根据缩放级别调整覆盖物大小及偏移 级别组
- function changeZoomByGroup() {
- let zoomLevel = bmap.value.getZoom().toFixed(0);
- if (cacheLevel.value == zoomLevel) return;
- cacheLevel.value = zoomLevel;
- switch (parseInt(zoomLevel)) {
- case 5: {
- prevLevel.value = 5;
- clearShipsOverlay();
- reDrewShips(0.2, 4);
- break;
- }
- case 6 || 7: {
- let arr = [6, 7];
- if (arr.includes(prevLevel.value)) return;
- prevLevel.value = 6;
- clearShipsOverlay();
- reDrewShips(0.4, 3);
- break;
- }
- case 8 || 9 || 10: {
- let arr = [8, 9, 10];
- if (arr.includes(prevLevel.value)) return;
- prevLevel.value = 8;
- clearShipsOverlay();
- reDrewShips(0.6, 2);
- break;
- }
- case 11 || 12 || 13 || 14: {
- let arr = [11, 12, 13, 14];
- if (arr.includes(prevLevel.value)) return;
- prevLevel.value = 11;
- clearShipsOverlay();
- reDrewShips(1);
- break;
- }
- }
- }
- // 根据缩放级别调整覆盖物大小及偏移 单级别
- function changeZoomByLevel() {
- let zoomLevel = bmap.value.getZoom().toFixed(0);
- if (cacheLevel.value == zoomLevel) return;
- cacheLevel.value = zoomLevel;
- switch (parseInt(zoomLevel)) {
- case 5: {
- clearShipsOverlay();
- reDrewShips(0.2, 134);
- break;
- }
- case 6: {
- clearShipsOverlay();
- reDrewShips(0.3, 116);
- break;
- }
- case 7: {
- clearShipsOverlay();
- reDrewShips(0.4, 99);
- break;
- }
- case 6: {
- clearShipsOverlay();
- reDrewShips(0.6, 66);
- break;
- }
- case 8: {
- clearShipsOverlay();
- reDrewShips(0.7, 50);
- break;
- }
- case 9: {
- clearShipsOverlay();
- reDrewShips(0.8, 34);
- break;
- }
- case 10: {
- clearShipsOverlay();
- reDrewShips(0.9, 18);
- break;
- }
- case 11 || 12 || 13 || 14: {
- let arr = [11, 12, 13, 14];
- if (arr.includes(prevLevel.value)) return;
- prevLevel.value = 11;
- clearShipsOverlay();
- reDrewShips(1);
- break;
- }
- }
- }
- // 重绘自定义船舶覆盖物
- function reDrewShips(scale, offset) {
- for (let i of shipsDataCache.value) {
- let overlay = cpxOverlay(i, scale, offset);
- shipsOverlayCache.value.push(overlay);
- bmap.value.addOverlay(overlay);
- }
- }
- watch(
- () => store.state.currentTabText,
- (a, b) => {
- if (a == "数字化赋能中心") return;
- store.dispatch("GetNumbers");
- isSafety.value = a == "运输安全管理中心";
- clearShipsOverlay();
- getAllShipLocation();
- }
- );
- // 轨迹缓存
- let polylineCache = ref({});
- // 轨迹方向箭头覆盖物缓存
- let arrowCache = ref([]);
- // 清除轨迹 及 轨迹箭头
- function clearPolyline() {
- bmap.value.removeOverlay(polylineCache.value);
- for (let i of arrowCache.value) {
- bmap.value.removeOverlay(i);
- }
- polylineCache.value = {};
- arrowCache.value = [];
- }
- // 查询选择船舶或地图点选船舶
- async function selectShip(item, cargo) {
- // if (!cargo) return;
- clearPolyline();
- let res;
- if (store.state.currentTabText == "运输安全管理中心") {
- res = await store.dispatch("GetManageShipDetail", item.key);
- }
- if (store.state.currentTabText == "智能交易中心") {
- res = await store.dispatch("GetTradeShipDetail", item.key);
- }
- return;
- if (res.length == 0) return;
- let points = [];
- for (let i of res) {
- points.push(new BMapGL.Point(i.lng, i.lat));
- }
- drawLine(points);
- }
- // 定义复杂覆盖物
- function cpxOverlay(
- item = {},
- scale = 1,
- offset = 0,
- offsetX = "0",
- offsetY = "0"
- ) {
- let { lng, lat, shipName, mmsi, cargo, tons, shipId } = item;
- // 复杂的自定义覆盖物
- function ComplexCustomOverlay(point) {
- this._point = point;
- }
- ComplexCustomOverlay.prototype = new BMapGL.Overlay();
- ComplexCustomOverlay.prototype.addEventListener = function (event, fun) {
- this._div["on" + event] = fun;
- };
- ComplexCustomOverlay.prototype.initialize = function (map) {
- this._map = map;
- let div = (this._div = document.createElement("div"));
- div.style.position = "absolute";
- div.style.margin = 0;
- div.style.padding = 0;
- div.style.zIndex = BMapGL.Overlay.getZIndex(this._point.lat);
- div.style.height = "0px";
- div.style.width = "0px";
- div.style.whiteSpace = "nowrap";
- div.style.MozUserSelect = "none";
- div.style.fontSize = "12px";
- div.style.cursor = "pointer";
- function parseDom(arg) {
- let objE = document.createElement("div");
- objE.innerHTML = arg;
- return objE;
- }
- let c2 = ` <div style="display: flex;
- align-items:center;position:relative;top:${offsetX}px;left:${offsetY}px">
- <div
- style="
- height: ${cargo ? "118px" : "60px"};
- width: 3px;
- box-sizing: border-box;
- background: rgb(16, 255, 185);
- border: 1px solid rgb(16, 255, 185);
- margin-right: 4px;
- "
- ></div>
- <div
- style="
- padding: 8px 12px;
- height: ${cargo ? "118px" : "60px"};
- width: 191px;
- background: rgba(0, 0, 0, 0.6);
- text-align: left;
- box-sizing: border-box;
- "
- >
- <div
- style="
- font-size: 18px;
- font-family: SourceHanSansSC-Bold, SourceHanSansSC;
- font-weight: bold;
- color: #10ffb9;
- margin-bottom: 1px;
- "
- >
- ${shipName}
- </div>
- <div
- style="
- font-size: 10px;
- font-family: SourceHanSansSC-Medium, SourceHanSansSC;
- font-weight: 500;
- color: #fafeff;
- margin-bottom: 10px;
- "
- >
- MMSI: ${mmsi}
- </div>
- <div
- style="
- display: ${cargo ? "flex" : "none"};
- font-size: 20px;
- font-family: DINAlternate-Bold, DINAlternate;
- font-weight: bold;
- color: #ffffff;
- "
- >
- <div style="margin-right: 35px">
- <div style="margin-bottom: 3px; height: 28px">${cargo}</div>
- <div
- style="
- font-size: 14px;
- font-family: SourceHanSansSC-Normal, SourceHanSansSC;
- font-weight: 400;
- color: #92afc7;
- "
- >
- 货种
- </div>
- </div>
- <div>
- <div
- style="
- margin-bottom: 3px;
- height: 28px;
- line-height:22px
- "
- >
- ${tons}
- <span style="display: inline-block; font-size: 16px"
- >吨</span
- >
- </div>
- <div
- style="
- font-size: 14px;
- font-family: SourceHanSansSC-Normal, SourceHanSansSC;
- font-weight: 400;
- color: #92afc7;
- "
- >
- 吨位
- </div>
- </div>
- </div>
- </div>
- </div>`;
- let content = `
- <div
- style="
- display: flex;
- align-items:center;
- text-shadow: 0px 0px 5px rgba(100, 185, 255, 0.6);
- position:relative;
- transform:scale(${scale});
- left:${137 * (scale - 1) + offset}px
- "
- >
- <img
- style="
- margin: 0px;
- padding: 0px;
- height: 55px;
- width: 55px;
- margin-right: 20px;
- "
- src="https://6875-huihenduo-2gx127w7f837b584-1255802371.tcb.qcloud.la/data-platform/map-ship-icon.png"
- alt=""
- />
- ${isSafety.value ? c2 : ""}
- </div>
- `;
- let shipBox = parseDom(content);
- div.addEventListener("click", function () {
- selectShip({ key: shipId }, cargo);
- });
- if (item != -1) {
- div.appendChild(shipBox);
- }
- bmap.value.getPanes().labelPane.appendChild(div);
- return div;
- };
- ComplexCustomOverlay.prototype.draw = function () {
- let map = this._map;
- let pixel = map.pointToOverlayPixel(this._point);
- this._div.style.left = pixel.x - 30 + "px";
- this._div.style.top = pixel.y - 65 + "px";
- };
- return new ComplexCustomOverlay(new BMapGL.Point(lng, lat));
- }
- // 轨迹绘制
- function drawLine(points) {
- // 定义覆盖物 线
- let polyline = new BMapGL.Polyline(points, {
- strokeWeight: "2", //折线的宽度,以像素为单位
- strokeColor: "#00ffb2", //折线颜色
- strokeStyle: "dashed", // 折线样式:虚线
- });
- polylineCache.value = polyline;
- bmap.value.addOverlay(polyline); //增加折线
- }
- // 船舶数据缓存
- let shipsDataCache = ref([]);
- // 船舶覆盖物缓存
- let shipsOverlayCache = ref([]);
- // 清除地图船舶覆盖物
- function clearShipsOverlay() {
- for (let i of shipsOverlayCache.value) {
- bmap.value.removeOverlay(i);
- }
- shipsOverlayCache.value = [];
- }
- // 获取所有船舶
- async function getAllShipLocation() {
- let res = await api[
- `${isSafety.value ? "getSafetyShipLocation" : "getAllShipLocation"}`
- ]();
- let data = res.data.result;
- // data.length = 30;
- shipsDataCache.value = data;
- for (let i of data) {
- let overlay = cpxOverlay(i);
- shipsOverlayCache.value.push(overlay);
- bmap.value.addOverlay(overlay);
- // let marker = new BMapGL.Marker( new BMapGL.Point(i.lng, i.lat));
- // marker.disableMassClear();
- // bmap.value.addOverlay(marker);
- }
- }
- let isSafety = ref(true);
- onMounted(() => {
- initMap();
- store.dispatch("GetNumbers");
- bmap.value.addOverlay(cpxOverlay(-1));
- isSafety.value = store.state.currentTabText == "运输安全管理中心";
- getAllShipLocation();
- });
- return {
- initMap,
- shipStr,
- selectShip,
- polylineCache,
- isSafety,
- };
- },
- };
- </script>
- <style lang="scss" scoped>
- #bmap {
- width: 100%;
- height: calc(100vh - 60px);
- box-sizing: border-box;
- background: #1d2c43;
- border-top: 1px solid grey;
- }
- :deep(.ship-search) {
- .el-input__inner {
- background: none;
- color: #fff;
- }
- }
- .mask {
- position: fixed;
- top: 60px;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 8;
- pointer-events: none;
- background-image: radial-gradient(ellipse, #213e5f, #0f1d2e);
- opacity: 0.35;
- }
- </style>
|