From 87e3d52c62233ad44bd7bac3f43e5348a2de4e94 Mon Sep 17 00:00:00 2001 From: luohairen <3399054449@qq.com> Date: 星期一, 25 十一月 2024 10:36:16 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- src/views/components/Map/index.vue | 585 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 585 insertions(+), 0 deletions(-) diff --git a/src/views/components/Map/index.vue b/src/views/components/Map/index.vue new file mode 100644 index 0000000..38f61f6 --- /dev/null +++ b/src/views/components/Map/index.vue @@ -0,0 +1,585 @@ +<template> + <div :id="id" ref="contentRef" style="height: 100%; width: 100%"> + <div + v-if="isShowControl" + :class="controlPosition" + class="control-container bottom-right" + > + <div + v-for="item in controlMapping" + :key="item.id" + class="control-content" + > + <template v-if="item.children"> + <div + v-for="child in item.children" + :key="child.id" + class="control-item" + @click="child.event" + > + <img :src="child.img" /> + </div> + </template> + <template v-else> + <div class="control-item" @click="item.event"> + <img :src="item.img" /> + </div> + </template> + </div> + </div> + </div> +</template> +<script> +import Location from "@/assets/images/location.png"; +import FileImg from "@/assets/images/file1.png"; +import MinusImg from "@/assets/images/minus.png"; +import PlusImg from "@/assets/images/plus.png"; +import FullScreenImg from "@/assets/images/fullScreen.png"; +import PositionImg from "@/assets/images/position.png"; +export default { + data() { + return { + zoom: 15, + map: null, + contentRef: {}, + infoWin: {}, + defaultMaskInfo: {}, + mapKey: "ffb871cd7ca48883db3b04cfd00d469f", + controlMapping: [ + { + id: "瀹氫綅", + img: PositionImg, + event: this.getCurrentPosition, + }, + { + id: "缂╂斁", + children: [ + { + id: "鏀惧ぇ", + img: PlusImg, + event: this.zoomIn, + }, + { + id: "缂╁皬", + img: MinusImg, + event: this.zoomOut, + }, + ], + }, + { + id: "鍏ㄥ睆", + img: FullScreenImg, + event: this.fullScreen, + }, + ], + }; + }, + props: { + id: String, + mapList: Array, + listType: Boolean, + isShowControl: Boolean, + controlPosition: Object, + isImmediateLoad: { type: Boolean, default: true }, + mapType: Boolean, + }, + + created() { + this.defaultMaskInfo = { + lon: this.$props.mapList[0]?.lon + ? this.$props.mapList[0].lon + : "105.37281", + lat: this.$props.mapList[0]?.lat + ? this.$props.mapList[0].lat + : "30.87145", + name: this.$props.mapList[0]?.name ? this.$props.mapList[0].name : "鍒涘缓", + }; + if (this.$props.isImmediateLoad) this.onLoad(); + }, + methods: { + async onLoad() { + const scripts = document.body.querySelectorAll("script"); + if (!this.mapKey) { + // const res = await getDicts('map_key') + // mapKey = res[0].dictLabel + this.mapKey = "ffb871cd7ca48883db3b04cfd00d469f"; + } + + const scriptSrc = `http://api.tianditu.gov.cn/api?v=4.0&tk=${this.mapKey}`; + const mapScript = Array.from(scripts).find((item) => { + return item.getAttribute("src") === scriptSrc; + }); + + if (!mapScript) { + // 鍒涘缓script鏍囩 + const script = document.createElement("script"); + // 璁剧疆API鐨刄RL + script.src = scriptSrc; + script.type = "text/javascript"; + // 灏唖cript鏍囩娣诲姞鍒癏TML涓� + document.body.appendChild(script); + script.onload = () => { + this.initTianMap(); + }; + } else { + this.initTianMap(); + } + }, + + initTianMap() { + var T = window.T; + setTimeout(async () => { + // this.map = new T.Map(this.id, { + // projection: "EPSG:4326", + // }); + this.map = new T.Map(this.id); + this.map.centerAndZoom( + new T.LngLat(this.defaultMaskInfo.lon, this.defaultMaskInfo.lat), + this.zoom + ); + if (!this.$props.listType) { + // 娓呴櫎涔嬪墠鐨勬爣璁� + // map && map.clearOverLays() + //form琛ㄥ崟涓槸鍚︽湁鍧愭爣锛屾湁鍒欏畾浣嶅埌瀵瑰簲浣嶇疆锛屾病鏈夊垯浣跨敤榛樿鐨� + // 104.65417 28.75572 娴嬭瘯鏁版嵁 + // 鍥涘窛鐪佸疁瀹惧競缈犲睆鍖哄ぇ瑙傛ゼ琛楅亾澶栧崡琛�71 + if (this.$props.mapList[0].addr) { + const { lng: lon, lat } = await this.getGeocode( + this.$props.mapList[0].addr + ); + this.defaultMaskInfo.lon = String(lon); + this.defaultMaskInfo.lat = String(lat); + } + + this.map && this.makeDefaultMask(this.defaultMaskInfo); + this.addEvent(this.map, "click", (e) => this.mapClick(e)); + } else { + this.$props.mapList.length && this.makeAllMask(this.$props.mapList); + } + }, 1500); + }, + + zoomIn() { + this.map && this.map.zoomIn(); + }, + + zoomOut() { + this.map && this.map.zoomOut(); + }, + + fullScreen() { + this.map && this.contentRef?.requestFullscreen(); + }, + + getCurrentPosition() { + if (navigator.geolocation) { + ElMessage.warning("璇ュ姛鑳芥殏鏈紑鍙�"); + // TODO 鍦板浘瀹氫綅 + // navigator.geolocation.getCurrentPosition(function (position) { + // var latitude = position.coords.latitude + // var longitude = position.coords.longitude + // + // moveTo(String(longitude), String(latitude)) + // }) + } else { + ElMessage.warning("褰撳墠娴忚鍣ㄤ笉鏀寔瀹氫綅鍔熻兘"); + } + }, + + moveTo(lon, lat) { + this.map && this.map.panTo(new T.LngLat(lon, lat)); + }, + + // 榛樿鐨勭偣鏍囪 + makeDefaultMask(mapInfo) { + const { name, lon, lat } = mapInfo + const option = { + text: name, + offset: [-35, -45], + labelBg: "#3369FF", + labelColor: "#fff", + labelClick, + }; + // 娓呴櫎涔嬪墠鐨勬爣璁� + this.map && this.map.clearOverLays(); + this.map.panTo(new T.LngLat(lon, lat)); + this.makeMask(lon, lat, { labelOptions: option }); + }, + + // 鍦板浘鐐瑰嚮浜嬩欢 + mapClick(e) { + e.originalEvent.stopPropagation(); + + const { lat, lng: lon } = e.lnglat; + + this.makeDefaultMask({ + ...defaultMaskInfo, + lon: String(lon), + lat: String(lat), + }); + this.getReverseGeocode(e).then((addr) => { + this.$emit("mapClick", { e, addr }); + }); + console.log("鐐瑰嚮浜嬩欢", e); + }, + + // 閫嗗湴鐞嗙紪鐮� 鑾峰彇鍦板潃 + getReverseGeocode(e) { + return new Promise((resolve) => { + const geocode = new T.Geocoder(); + geocode.getLocation(e.lnglat, (result) => { + if (result.status === "0") { + resolve(result.getAddress()); + } + }); + }); + }, + + // 鍦扮悊缂栫爜 + getGeocode(addr) { + return new Promise((resolve) => { + const geocoder = new T.Geocoder(); + geocoder.getPoint(addr, (result) => { + if (result.status === "0") { + resolve(result.getLocationPoint()); + } + }); + }); + }, + + // 鐢熸垚鐐逛綅鍐呭 + // 鐢熸垚鐐逛綅鍐呭 + generateContent(row, random) { + if (row) { + return ` + <div class="map-window-info"> + <div class='title-block'> + <div class="title truncate-content"> + ${row.projectName ?? "鏆傛棤鏁版嵁"} + </div> + <div class='close-btn close-btn-${random}'> + 脳 + </div> + </div> + <div class="detail-info"> + <span class="truncate-content">鎬绘姇璧勶細${row.totalMoney ?? "鏆傛棤鏁版嵁" + }</span> + <span class="truncate-content"> + 椤圭洰鐘舵�侊細 + </span> + <span class="truncate-content"> + 椤圭洰鍦板潃锛�${row.projectAddr ?? "鏆傛棤鏁版嵁"} + </span> + </div> + </div>`; + } else { + return `<div style="display: flex; justify-content:center; align-items:center; opacity: 0;"> + + </div>`; + } + }, + + // 鍞竴鏍囪瘑 + getUniqueId() { + return Math.random().toString(36).substr(2) + Date.now(); + }, + + markerMouseover(_e, infoWin, info, random) { + // 鐐逛綅鏍囪绉诲叆鏄剧ず涓嶅悓鍐呭 + if (this.$props.isShowControl) { + infoWin.setContent(this.generateContent(info, random)); + const contentWrapper = document.querySelector( + ".tdt-infowindow-content-wrapper" + ); + if (contentWrapper) { + contentWrapper.style.opacity = "1"; + } + // 鏌ユ壘鍒伴偅涓猧nfo 鐣岄潰 + // const allCloseBtn = document.querySelectorAll(`.close-btn-${random}`); + // allCloseBtn[allCloseBtn.length - 1].onclick = (_e) => { + // infoWin.setContent(generateContent()); + // }; + } + }, + + markerMouseout(_e, infoWin) { + infoWin.setContent(this.generateContent()); + const contentWrapper = document.querySelector( + ".tdt-infowindow-content-wrapper" + ); + if (contentWrapper) { + contentWrapper.style.opacity = "0"; + } + }, + + // 鎵撴爣璁� + makeMask(lon, lat, options) { + + const { markerOptions, labelOptions } = options; + console.log("options", markerOptions, labelOptions); + const icon = new T.Icon({ + iconUrl: Location, + iconSize: new T.Point(19, 27), + iconAnchor: new T.Point(10, 25), + }); + var marker = new T.Marker(new T.LngLat(lon, lat), { + icon, + id: markerOptions?.id, + }); + + this.map && this.map.addOverLay(marker); + const label = new T.Label({ + text: labelOptions.text, + position: new T.LngLat(lon, lat), + offset: new T.Point(...labelOptions.offset), + id: labelOptions?.id, + }); + + labelOptions.labelBg && label.setBackgroundColor(labelOptions.labelBg); + labelOptions.labelColor && label.setFontColor(labelOptions.labelColor); + //鍒涘缓鍦板浘鏂囨湰瀵硅薄 + if (!this.$props.mapType) { + this.map && this.map.addOverLay(label); + } + markerOptions?.markerClick && + this.addEvent(marker, "click", (e) => markerOptions.markerClick(label, e)); + labelOptions?.labelClick && + this.addEvent(label, "click", (e) => labelOptions.labelClick(label, e)); + + const lnglat = new T.LngLat(lon, lat); + const infoWin = new T.InfoWindow(this.generateContent(), { + id: markerOptions?.id, + offset: new T.Point(0, -15), + closeButton: false, + }); + + infoWin.setLngLat(lnglat); + // 鍚戝湴鍥句笂娣诲姞淇℃伅绐楀彛 + if (this.$props.mapType) { + this.map && this.map.addOverLay(infoWin); + } + + this.addEvent(marker, "mouseover", (e) => + markerMouseover(e, infoWin, labelOptions, getUniqueId()) + ); + this.addEvent(marker, "mouseout", (e) => markerMouseout(e, infoWin)); + }, + + // 鏍囪鎵�鏈夌偣 + makeAllMask(mapList) { + var _this = this; + this.mapList.map((item) => { + const config = { + markerOptions: { + id: item.id, + markerClick: _this.markerClick, + }, + labelOptions: { + text: item.name, + offset: [-45, -45], + id: item.id, + markerClick: _this.labelClick, + }, + }; + _this.makeMask(item.lon, item.lat, config); + }); + }, + + // 閫氱敤娣诲姞浜嬩欢鐨勬柟娉� + addEvent(component, name, func) { + // 绉诲嚭浜嬩欢 + this.removeEvent(component, name, func); + // 娣诲姞浜嬩欢 + component.addEventListener(name, func); + }, + + // 閫氱敤绉诲嚭浜嬩欢鐨勬柟娉� + removeEvent(component, name, func) { + component.removeEventListener(name, func); + }, + + //鏍囪鐐瑰嚮浜嬩欢 + markerClick(currentLabel, e) { + const id = e.target.options.id; + currentLabelStyleChange(currentLabel); + console.log("鐐瑰嚮浜嬩欢", e, currentLabel); + this.getReverseGeocode(e).then((addr) => { + this.$emit( + "markClick", + id + ? this.$props.mapList?.find((item) => item.id === id) + : { e, addr: addr } + ); + }); + }, + + // label鐐瑰嚮浜嬩欢 + labelClick(currentLabel, e) { + const id = e.target.options.id; + currentLabelStyleChange(currentLabel); + getReverseGeocode(e).then((addr) => { + this.$emit( + "labelClick", + id + ? this.$props.mapList?.find((item) => { + return String(item.id) === String(id); + }) + : { e, addr: addr } + ); + }); + }, + + currentLabelStyleChange(currentLabel) { + this.$emit("currentLabelStyleChange", currentLabel); + }, + + resizeMap() { + this.map.checkResize(); + }, + }, + watch: { + listType: { + handler(val) { + if (val) { + this.map && this.map.clearOverLays(); + if (this.$props.mapList.length && T) { + this.makeAllMask(this.$props.mapList); + } + } + }, + }, + }, + beforeUnmount() { + this.map = null; + }, +}; + +// const emits = defineEmits<{ +// (e: 'labelClick', value: any): void; +// (e: 'markClick', value: any): void; +// (e: 'mapClick', value: any): void; +// (e: 'currentLabelStyleChange', value: any): void; +// }>(); +</script> +<style lang="scss" scoped> +:deep(.tdt-label) { + border-radius: 15px; + color: var(--el-color-primary); + cursor: pointer; +} + +// #53547f +:deep(.tdt-bar a, .tdt-bar a:hover) { + border-bottom: 0; + color: #53547f; +} + +:deep(.tdt-touch .tdt-control-zoom-in) { + font-size: 18px; +} + +:deep(.tdt-bar) { + border-radius: 3px; + box-shadow: 5px 0px 12px 0px rgb(0 0 0 / 0.03); +} + +.tdt-bar a.tdt-disabled, +.tdt-bar a:hover { + background-color: #f4f4f4; +} + +.control-container { + position: absolute; + display: flex; + flex-direction: column; + gap: 10px; + z-index: 999; +} + +.top-left { + top: 10px; + left: 10px; +} + +.top-right { + top: 10px; + right: 10px; +} + +.bottom-left { + bottom: 10px; + left: 10px; +} + +.bottom-right { + bottom: 10px; + right: 10px; +} + +.control-content { + border-radius: 3px; + box-shadow: 5px 0px 12px 0px rgb(0 0 0 / 0.03); + background-color: #fff; +} + +.control-item { + box-sizing: border-box; + width: 30px; + height: 30px; + line-height: 28px; + padding: 0 9px; + + img { + display: inline-block; + } +} + +.control-item:hover { + background-color: #f4f4f4; +} +</style> +<style lang="scss"> +.map-window-info { + padding: 0 20px; + width: 300px; + cursor: default; + + .title { + color: #3369ff; + font-size: 18px; + margin-bottom: 13px; + } + + .detail-info { + display: flex; + flex-direction: column; + color: #7e809c; + font-size: 12px; + gap: 8px; + } +} + +.title-block { + display: flex; + justify-content: space-between; + + .close-btn { + font-size: 18px; + color: #d8dde6; + cursor: pointer; + z-index: 999999; + } +} + +//.tdt-control-copyright { +// display: none; +//} + +.tdt-infowindow-tip-container { + opacity: 0; +} + +.tdt-infowindow-content-wrapper { + opacity: 0; +} +</style> -- Gitblit v1.8.0