Vue3 + 腾讯地图初始化
1 开发者账号注册
- 去腾讯位置服务控制台注册账号并进入我的应用界面
- 创建应用,保留生成的 key
2 引入项目
在 index.html 中引入资源,注意连接中的 key 参数要换成第一步中应用的 key 值
html<script src="https://map.qq.com/api/gljs?v=1.exp&key=xxxx"></script>
3 初始化地图
详情参考官网文档
新建一个组合式函数用于初始化地图
src/composables/map/useInitMap.js
jsimport { reactive, onMounted } from 'vue'; export default function useInitMap(domId, center) { let map = reactive({ dom: null, instance: null, }); const initMap = () => { map.dom = document.getElementById(domId); map.instance = new window.TMap.Map(map.dom, { center: new window.TMap.LatLng(...center), // 中心点坐标 zoom: 17.2, // 缩放级别 pitch: 43.5, // 俯仰角 rotation: 45, // 地图旋转角度 }); }; onMounted(() => { initMap(); }); return { map }; }
在页面中使用
vue<script setup> import useInitMap from '../composables/map/useInitMap'; let { map } = useInitMap({ domId: 'map', center: [39.98412, 116.307484] }); </script> <template> <div id="map"></div> </template>
4 定位组件
详情参考官网文档
在
index.html
内引入组件,注意填入提前准备好的 keyhtml<script src="https://apis.map.qq.com/tools/geolocation/min?key=xxxx&referer=myapp"></script>
创建一个组合式函数用于使用定位组件
src/composables/map/useLocation.js
jsimport { onBeforeUnmount, onMounted, reactive } from 'vue'; export default function useLocation(map) { let geolocation = reactive({ location: null, instance: null, }); // 获取一次当前定位 const getLocation = () => { geolocation.instance.getLocation( (position) => { geolocation.location = position; }, (err) => { console.error('定位获取失败:', err); }, { timeout: 8000 } ); }; // 当前定位居中显示 const setCenter = () => { const { lat, lng } = geolocation.location; const center = new window.TMap.LatLng(lat, lng); map.instance.setCenter(center); }; // 每 5 秒刷新一次定位,注意此处要用实际的 key 替换 xxxx let timerPosition = null; onMounted(() => { geolocation.instance = new window.qq.maps.Geolocation('xxxx', 'myapp'); timerPosition = setInterval(() => { getLocation(); }, 5000); }); onBeforeUnmount(() => { clearInterval(timerPosition); // 停止监听 }); return { geolocation, getLocation, setCenter, }; }
在页面中使用
vue<script setup> import { onMounted } from 'vue'; import useInitMap from '../composables/map/useInitMap'; import useLocation from '../composables/map/useLocation'; let { map } = useInitMap({ domId: 'map' }); let { getLocation, geolocation, setCenter } = useLocation(map); onMounted(() => { getLocation(); }); </script> <template> <div id="map"></div> <button @click="setCenter">setCenter</button> <pre>{{ geolocation.location }}</pre> </template>
5 自定义覆盖物
自定义覆盖物可以继承构造函数的方法来创建一个类,
src/utils/mapOverlay/OverlayImg.js
js// 自定义图片覆盖物 export default class OverlayImg extends window.TMap.DOMOverlay { constructor(options) { super(options); } // 初始化:获取配置参数 onInit({ position, src, map } = {}) { Object.assign(this, { position, src, map }); } // 创建DOM元素,返回一个Element,使用this.dom可以获取到这个元素 createDOM() { this.onMouseEnter = function (e) { this.emit('mouseenter', e.target.firstChild); }.bind(this); this.onMouseLeave = function (e) { this.emit('mouseleave', e.target.firstChild); }.bind(this); this.onClick = function (e) { this.emit('click', e.target.firstChild); }.bind(this); let mydom = document.createElement('div'); mydom.innerHTML = ''; mydom.style.cssText = `background-image: url('${this.src}');`; mydom.setAttribute('class', 'overlayImg'); mydom.addEventListener('click', this.onClick); mydom.addEventListener('mouseenter', this.onMouseEnter); mydom.addEventListener('mouseleave', this.onMouseLeave); return mydom; } // 更新DOM元素,在地图移动/缩放后执行 updateDOM() { if (!this.map) { return; } // 经纬度坐标转容器像素坐标 let position = new window.TMap.LatLng(...this.position); let pixel = this.map.projectToContainer(position); // 使图中心点对齐经纬度坐标点 let left = pixel.getX() - this.dom.clientWidth / 2 + 'px'; let top = pixel.getY() - this.dom.clientHeight / 2 + 'px'; this.dom.style.transform = `translate(${left}, ${top})`; } // 销毁时 onDestroy() { if (this.onClick) { this.dom.removeEventListener(this.onClick); } if (this.onMouseLeave) { this.dom.removeEventListener(this.onMouseLeave); } if (this.onMouseEnter) { this.dom.removeEventListener(this.onMouseEnter); } } }
在页面中使用,让一个图片动起来
vue<script setup> import { onMounted } from '@vue/runtime-core'; import useInitMap from '../composables/map/useInitMap'; import OverlayImg from '../utils/mapOverlay/OverlayImg.js'; let { map } = useInitMap({ domId: 'map' }); onMounted(() => { new OverlayImg({ map: map.instance, position: [39.98412, 116.307484], src: '/man.png', }); }); </script> <template> <div id="map"></div> </template> <style lang="scss"> .overlayImg { width: 200px; height: 200px; background-repeat: no-repeat; background-position: -800px 0; animation: man_run 1s steps(7, end) both infinite; } @keyframes man_run { 0% { background-position: -800px 0; } 100% { background-position: -2200px 0; } } </style>