【資料圖】
在我們使用高德地圖的時(shí)候,官方給我們推薦了很多案例,demo,但是這些案例都是使用原生方法接入,并沒有提供vue或者react的demo,vue2的 接入網(wǎng)上也很多人都有寫過,下面本篇文章就來看看 vue3怎么使用常用的高德地圖api,希望對(duì)大家有所幫助!
npm i @amap/amap-jsapi-loader --save
import AMapLoader from "@amap/amap-jsapi-loader"
使用官方介紹的方式進(jìn)行加
vue2和 vue3是有區(qū)別的,這里我們使用的是 vue3,但這里 vue3的方式還是選項(xiàng)式,不是組合式的,我自己寫的時(shí)候使用的是組合式的,且集成了ts, 我后面發(fā)布完整 .vue文件的時(shí)候 會(huì)去掉標(biāo)簽上的 ts,因?yàn)轭愋瓦€沒有完善,等后面完善了再貼更改以后得。為什么要使用 shallowRef官方也給出了說明原因。 【相關(guān)推薦:vuejs視頻教程、web前端開發(fā)】
這里我直接把我前面,寫過的 地圖業(yè)務(wù)需求的業(yè)務(wù)邏輯拿過來的,沒有使用框架,直接在一個(gè) html 文件當(dāng)中引入,鏈接大家可以點(diǎn)擊下面進(jìn)行查看:高德地圖jsApi的使用高德地圖jsApi的點(diǎn)和線配置高德地圖jsApi的右鍵設(shè)置高德地圖jsApi的點(diǎn)位新增高德地圖jsApi的圖例使用vue3的時(shí)候,實(shí)例化的方式, this的問題, 以及插入字符串模板的時(shí)候 事件響應(yīng)的方式都需要更改,還是很麻煩的
plugins加載插件, 其他配置如 Loca, 直接進(jìn)行配置, 這里需要注意版本問題, 寫成 ‘2.0’ 是不行的,初始化函數(shù)在 onmounted生命周期中執(zhí)行。AMap存儲(chǔ)這里我做了很多存儲(chǔ),大家知道 .value的語法是 vue3獲取 ref的語法,我下面使用到的 都是ref,后面完整代碼可以查看, 這里掛載的時(shí)候直接存一下,因?yàn)楹芏喙ぞ叻椒ǘ紩?huì)只用到他,這里后期業(yè)務(wù)邏輯我會(huì)抽離到 pinia中去,所以不需要在初始化函數(shù)中寫全部的業(yè)務(wù)邏輯。模版樣式不生效問題, 我們?cè)谑褂玫臅r(shí)候, 就像我之前寫的文章,點(diǎn)位新增的時(shí)候,我們會(huì)插入 content 字符串模版,替換點(diǎn)樣式,這里有兩種方案修改樣式,一種是 插入 DOM,不使用字符串,然后在 DOM 上通過 style直接修改樣式,另一種就是使用模版的時(shí)候直接給 class類名,但是這種樣式如果我們給 vue的 style加了 scoped就不會(huì)生效,這里大家可以自己靈活選擇用哪種,我這里暫時(shí)先使用模版的方式,去掉了 scoped。圖例, 圖例這里除了導(dǎo)入的時(shí)候,需要配置一下,使用上來說變化不大,樣式的修改還是復(fù)用了我之前的邏輯。import AMapLoader from "@amap/amap-jsapi-loader"const initMap = () => { AMapLoader.load({ key: "b59c490f61a694b9d7576dd864f74d6e", // 申請(qǐng)好的Web端開發(fā)者Key,首次調(diào)用 load 時(shí)必填 version: "2.0", // 指定要加載的 JSAPI 的版本,缺省時(shí)默認(rèn)為 1.4.15 plugins: ["AMap.Scale", "AMap.ToolBar", "AMap.MouseTool"], // 需要使用的的插件列表,如比例尺"AMap.Scale"等 Loca:{ version:"2.0.0" } }) .then((res) => { AMap.value = res // 上來就顯示的中心點(diǎn) 北京 116.397, 39.918 var lnglat = new res.LngLat(105, 38) map.value = new res.Map("container", { //設(shè)置地圖容器id viewMode: "3D", //是否為3D地圖模式 zoom: 5, //初始化地圖級(jí)別 center: lnglat, //初始化地圖中心點(diǎn)位置 }) map.value.clearMap() // 清除地圖覆蓋物 // 地圖是否可拖拽和縮放 map.value.setStatus({ dragEnable: true, // 是否可拖拽 zoomEnable: true, // 是否可縮放 }) initWindow() // 添加一些分布不均的點(diǎn)到地圖上,地圖上添加三個(gè)點(diǎn)標(biāo)記,作為參照 coordData.forEach(function (marker) { setMarker(marker) }) let renderLine = setLine(coordData) // 設(shè)置線 let polyline = renderLine.reduce((prev, item, index) => { let weight = item.type === 1 ? 5 : 3 let color = item.type === 1 ? headColors[0] : headColors[1] prev.push(setLines(item.current, color, weight)) return prev }, []) map.value.add([...polyline]) // 繪制線 //創(chuàng)建右鍵菜單 menuInstance.value = new ContextMenu(map.value) let loca = new Loca.Container({ map:map.value, }); window._loca = loca; // 圖例, 圖例可以實(shí)例化多個(gè),使用定位來設(shè)置位置 let lengend = new Loca.Legend({ loca: loca, title: { label: "管道類型", fontColor: "rgba(255,255,255,1)", fontSize: "16px" }, style: { backgroundColor: "rgba(255,255,255,0.2)", left: "20px", bottom: "40px", fontSize: "12px" }, dataMap: [ { label: "省級(jí)管道", color: headColors[1] }, { label: "縣級(jí)管道", color: headColors[0] }, ], }); //修改圖例排列方式 document.getElementsByClassName("amap-loca loca-controls")[0].setAttribute("id", "testid") var lis = document.querySelectorAll("#testid li"); for (var i = 0; i < lis.length; i++) { console.log(lis[i]); lis[i].setAttribute("class", "test" ); } }) .catch((e) => { console.log("error", e) })}onMounted(() => { initMap()})右鍵菜單, 右鍵菜單這里官方給我們的示例是使用一個(gè) 函數(shù) 進(jìn)行實(shí)例化,里面使用了 this, 所以這個(gè)我單獨(dú)拿出來,首先我們看一下官方的 demo
this,實(shí)話來講,這種寫法確實(shí)不是很優(yōu)秀,可擴(kuò)展性很差,不夠健壯,但沒辦法,誰讓我們用了人家的東西呢是吧, 在 vue3中這么用就不可以了,首先 vue3里面使用 this就不是官方建議的, 另外這里面還修改了函數(shù)原型上的方法,其實(shí)我得代碼里面一共有兩種右鍵菜單,如下:一種是在指定點(diǎn)位上打開,另一種是在非點(diǎn)位的空白處打開,指定點(diǎn)位處打開的其實(shí)叫信息窗體,只不過是通過右鍵的方式觸發(fā),那個(gè)沒有上面這個(gè)右鍵菜單麻煩。
首先來說this問題, 這里的 this實(shí)際上就是把我們的實(shí)例化對(duì)象掛載到上面而已,vue3中沒辦法像 vue2那樣使用 this, 但也提供給我們了 api來獲取當(dāng)前組件的實(shí)例化對(duì)象, 然后我沒用使用函數(shù), 使用了一個(gè)類,類構(gòu)造這個(gè)方法, 模版也不適用字符串模版,因?yàn)檫@里字符串模版的事件綁定寫死了,我們使用 DOM來動(dòng)態(tài)綁定事件,代碼如下:const { ctx } = getCurrentInstance()const _this = ctx//自定義菜單類class ContextMenu { constructor(map) { var me = _this //地圖中添加鼠標(biāo)工具M(jìn)ouseTool插件 _this.mouseTool = new AMap.value.MouseTool(map) _this.contextMenuPositon = null const fragment = document.createElement("div") // 使用 DOM 方式, 方便添加事件 fragment.className = "info context_menu" const p = document.createElement("p") p.addEventListener("click", this.delMarkerMenu) p.textContent = "移除上次選中信息" fragment.appendChild(p) //通過content自定義右鍵菜單內(nèi)容 _this.contextMenu = new AMap.value.ContextMenu({ isCustom: true, content: fragment, }) //地圖綁定鼠標(biāo)右擊事件——彈出右鍵菜單 map.on("rightclick", function (e) { me.contextMenu.open(map, e.lnglat) me.contextMenuPositon = e.lnglat //右鍵菜單位置 }) } delMarkerMenu() { // 右鍵菜單上次選中點(diǎn)的信息 clearPoint() _this.mouseTool.close() _this.contextMenu.close() }}<!-- * @Description: 地圖 * @Autor: codeBo * @Date: 2023-03-06 16:10:10 * @LastEditors: gjzxlihaibo@163.com * @LastEditTime: 2023-03-07 14:59:08--><template> <div id="root"> <div> <h3>添加選點(diǎn)請(qǐng)輸入坐標(biāo)</h3> <label> 經(jīng)度: <input /> </label> <label> 緯度: <input /> </label> <button>輸入完成</button> <button>清空輸入</button> </div> <div id="container"></div> </div></template><script setup>import { onMounted, reactive, ref, getCurrentInstance } from "vue"import AMapLoader from "@amap/amap-jsapi-loader"import { shallowRef } from "vue"import { coordData } from "./data"const map = shallowRef(null)const { ctx } = getCurrentInstance()const _this = ctxconst menuInstance = ref() // menu 實(shí)例let AMap = ref() // map 實(shí)例let currentPonit = ref<HTMLElement | null>(null) // 存儲(chǔ)當(dāng)前選中點(diǎn) DOMlet currentData = reactive({}) // 當(dāng)前選重點(diǎn)信息let sourceInfoWindow = ref()const headColors = ["#3366bb", "#6622FF"]// 工具方法// 修改DOM 類名function changeStyle(res, data) { if (currentPonit.value !== null) { currentPonit.value.classList.remove("active") } currentPonit.value = res.children[0] currentData = data currentPonit.value.classList.add("active")}// 清除點(diǎn)信息function clearPoint() { if (currentPonit.value) { currentPonit.value.classList.remove("active") } currentPonit.value = null currentData = {}}// 設(shè)置線信息function setLines(lnglat, color, weight) { return new AMap.value.Polyline({ path: lnglat, // showDir:true ,// 設(shè)置線方向 strokeColor: color, // 線顏色 strokeWeight: weight, // 線寬 strokeOpacity: 0.6, // 透明度 })}function markerClick(e) { console.log("sourceInfoWindow.value", sourceInfoWindow.value, e.target) sourceInfoWindow.value.setContent(e.target.contents) sourceInfoWindow.value.open(map.value, e.target.getPosition())}function setInput(e, name) { let text = e.target.parentElement.parentElement.children[0].innerText.split( "供給點(diǎn)", )[0] let current = coordData.filter((item) => { return item.name === text }) window.localStorage.setItem(text + name, e.target.value)}const initWindow = () => { // 信息窗體 let infoWindow = new AMap.value.InfoWindow({ offset: new AMap.value.Pixel(0, -10), retainWhenClose: true, }) sourceInfoWindow.value = infoWindow infoWindow.on("open", function (...arg) { let inputOut = document.getElementById("inputOut") let inputPro = document.getElementById("inputPro") inputOut.addEventListener("change", (e) => { setInput(e, "inputOut") window.location.reload() }) inputPro.addEventListener("change", (e) => { setInput(e, "inputPro") window.location.reload() }) })}// 抽離點(diǎn)位信息設(shè)置function setMarker(marker) { //創(chuàng)建右鍵菜單 var contextMenu = new AMap.value.ContextMenu() //右鍵放大 contextMenu.addItem( "放大一級(jí)", function () { map.value.zoomIn() }, 0, ) //右鍵縮小 contextMenu.addItem( "縮小一級(jí)", function () { map.value.zoomOut() }, 1, ) contextMenu.addItem("設(shè)置起點(diǎn)", function () { console.log("設(shè)置起點(diǎn)", marker, markerd.dom) changeStyle(markerd.dom, marker) contextMenu.close() // 關(guān)閉右鍵菜單 }) contextMenu.addItem("與起點(diǎn)連線", function () { if (!currentPonit) { alert("請(qǐng)選擇起點(diǎn)") contextMenu.close() return } else { // 這里其實(shí)可以根據(jù)數(shù)據(jù)判定線類型了,因?yàn)榈诙€(gè)選中點(diǎn)的信息+和第一個(gè)選中點(diǎn)的信息都有了,但是過濾方法會(huì)比較復(fù)雜 let path = [currentData.position, marker.position] const polyline1 = setLines(path, "#3366bb", 5) map.value.add([polyline1]) clearPoint() } contextMenu.close() // 關(guān)閉右鍵菜單 }) let content = "<div></div>" var markerd = new AMap.value.Marker({ map: map.value, // icon: marker?.icon, content, offset: new AMap.value.Pixel(-8, -8), visible: true, // 點(diǎn)標(biāo)記是否可見 position: [marker.position[0], marker.position[1]], }) let inputO = window.localStorage.getItem(marker.name + "inputOut") let inputP = window.localStorage.getItem(marker.name + "inputPro") // 左鍵點(diǎn)擊的信息窗體, 寬度會(huì)在碰觸到容器邊緣的時(shí)候自適應(yīng)的縮小 markerd.contents = ` <div>${marker.name}供給點(diǎn)</div> <div>出口壓力:<input id="inputOut" value="${ inputO ?? marker?.pointData?.out }"/>kPa</div> <div>供給量:<input id="inputPro" value="${ inputP ?? marker?.pointData?.provide }" />m3</div> <div>位置:經(jīng)度${marker.position[0]},緯度${marker.position[1]}</div>` markerd.data = marker markerd.on("click", markerClick) if (marker.name === "新疆") { // 觸發(fā)上面的點(diǎn)擊事件 markerd.emit("click", { target: markerd }) } //綁定鼠標(biāo)右擊事件——彈出右鍵菜單 markerd.on("rightclick", function (e) { contextMenu.open(map.value, e.lnglat) }) return markerd}//自定義菜單類class ContextMenu { constructor(map) { var me = _this //地圖中添加鼠標(biāo)工具M(jìn)ouseTool插件 _this.mouseTool = new AMap.value.MouseTool(map) _this.contextMenuPositon = null const fragment = document.createElement("div") // 使用 DOM 方式, 方便添加事件 fragment.className = "info context_menu" const p = document.createElement("p") p.addEventListener("click", this.delMarkerMenu) p.textContent = "移除上次選中信息" fragment.appendChild(p) //通過content自定義右鍵菜單內(nèi)容 _this.contextMenu = new AMap.value.ContextMenu({ isCustom: true, content: fragment, }) //地圖綁定鼠標(biāo)右擊事件——彈出右鍵菜單 map.on("rightclick", function (e) { me.contextMenu.open(map, e.lnglat) me.contextMenuPositon = e.lnglat //右鍵菜單位置 }) } delMarkerMenu() { // 右鍵菜單上次選中點(diǎn)的信息 clearPoint() _this.mouseTool.close() _this.contextMenu.close() }}// 過濾線方法function setLine(arr) { return arr.reduce((prev, item) => { if (item?.line) { prev.push(...item.line) } return prev }, [])}const initMap = () => { AMapLoader.load({ key: "b59c490f61a694b9d7576dd864f74d6e", // 申請(qǐng)好的Web端開發(fā)者Key,首次調(diào)用 load 時(shí)必填 version: "2.0", // 指定要加載的 JSAPI 的版本,缺省時(shí)默認(rèn)為 1.4.15 plugins: ["AMap.Scale", "AMap.ToolBar", "AMap.MouseTool"], // 需要使用的的插件列表,如比例尺"AMap.Scale"等 Loca:{ version:"2.0.0" } }) .then((res) => { AMap.value = res // 上來就顯示的中心點(diǎn) 北京 116.397, 39.918 var lnglat = new res.LngLat(105, 38) map.value = new res.Map("container", { //設(shè)置地圖容器id viewMode: "3D", //是否為3D地圖模式 zoom: 5, //初始化地圖級(jí)別 center: lnglat, //初始化地圖中心點(diǎn)位置 }) map.value.clearMap() // 清除地圖覆蓋物 // 地圖是否可拖拽和縮放 map.value.setStatus({ dragEnable: true, // 是否可拖拽 zoomEnable: true, // 是否可縮放 }) initWindow() // 添加一些分布不均的點(diǎn)到地圖上,地圖上添加三個(gè)點(diǎn)標(biāo)記,作為參照 coordData.forEach(function (marker) { setMarker(marker) }) let renderLine = setLine(coordData) // 設(shè)置線 let polyline = renderLine.reduce((prev, item, index) => { let weight = item.type === 1 ? 5 : 3 let color = item.type === 1 ? headColors[0] : headColors[1] prev.push(setLines(item.current, color, weight)) return prev }, []) map.value.add([...polyline]) // 繪制線 //創(chuàng)建右鍵菜單 menuInstance.value = new ContextMenu(map.value) let loca = new Loca.Container({ map:map.value, }); window._loca = loca; // 圖例, 圖例可以實(shí)例化多個(gè),使用定位來設(shè)置位置 let lengend = new Loca.Legend({ loca: loca, title: { label: "管道類型", fontColor: "rgba(255,255,255,1)", fontSize: "16px" }, style: { backgroundColor: "rgba(255,255,255,0.2)", left: "20px", bottom: "40px", fontSize: "12px" }, dataMap: [ { label: "省級(jí)管道", color: headColors[1] }, { label: "縣級(jí)管道", color: headColors[0] }, ], }); //修改圖例排列方式 document.getElementsByClassName("amap-loca loca-controls")[0].setAttribute("id", "testid") var lis = document.querySelectorAll("#testid li"); for (var i = 0; i < lis.length; i++) { console.log(lis[i]); lis[i].setAttribute("class", "test" ); } }) .catch((e) => { console.log("error", e) })}onMounted(() => { initMap()})</script><style>#container { width: 1350px; height: 900px;}#root { display: flex; width: 100%;}#root > div:first-child { width: 200px; margin-right: 10px; padding: 5px; box-shadow: 2px 2px 2px 2px #333;}#root > div:first-child { display: flex; flex-direction: column;}.context_menu { position: relative; min-width: 12rem; padding: 0; background-color: white;}.context_menu p { cursor: pointer; padding: 0.25rem 1.25rem;}.context_menu p:hover { background: #ccc;}.btn { width: 80px; margin-top: 10px;}.marker-route { width: 15px; height: 15px; background-color: #22ddb8; border-radius: 10px;}.active { background-color: #f76809;}.content { background-color: rgba(0, 0, 0, 0.3); padding: 1px; color: white; display: flex; align-items: center;}.content span { display: block; width: 20px; height: 20px; background-color: #3366bb; margin: 0 10px;}.content p { margin-right: 10px;}.test { height: 30px; box-sizing: content-box; padding: 2px 10px; line-height: 30px; display: inline; float: left;}.test a { color: #333 !important;}.test span { width: 80px !important; margin-left: 10px; border-radius: 10px;}.amap-info-content { background-color: rgba(255, 255, 255, 0.6);}.test_container { background-color: rgba(255, 255, 255, 0.6); display: flex; width: 180px; flex-direction: column; padding: 10px 18px 10px 10px; line-height: 1.4; overflow: auto; justify-content: center; align-items: center; border: 1px solid rgba(0, 0, 0, 0.2);}.input_inner { margin-right: 5px; border: 1px solid #333; border-radius: 2px; width: 30px;}</style>這里的業(yè)務(wù)邏輯還不完善, 輸入部分的交互邏輯沒有完成, 這個(gè)文件直接引入自己的項(xiàng)目,安裝一下上面說過的依賴, 就可以使用,不過這里數(shù)據(jù)源需要自己根據(jù)自己的數(shù)據(jù)來構(gòu)造就可以了,我引入的事 data中的一組假數(shù)據(jù),在這里給大家兩組看一下export const coordData = [ { name: "黑龍江", position: [127, 47], pointData: { out: 100, provide: 10, }, line: [ { current: [ [127, 47], [126, 43], ], type: 1, }, ], }, { name: "吉林", position: [126, 43], pointData: { out: 120, provide: 11, }, line: [ { current: [ [126, 43], [113, 41], ], type: 1, }, ], }, ]后面我會(huì)把業(yè)務(wù)邏輯抽離到 pinia中, 并且完善ts類型, 大家對(duì)哪一部分有疑問或者更好的解決方案可以留言一起學(xué)習(xí)~(學(xué)習(xí)視頻分享:vuejs入門教程、編程基礎(chǔ)視頻)
以上就是聊聊vue3中怎么使用高德地圖api的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
關(guān)鍵詞: