UNPKG

czmap

Version:

- 提供统一的API 实现不同的地图(百度、高德、腾讯)应用 丝滑切换 - 主要实现功能 - 基础地图展示 - 路径 - 围栏 #### 相关API使用

632 lines (609 loc) 20.9 kB
class CMap { constructor(options) { this.$options = options this.mapAk = ''; this.map = '' const { type } = options if (window.$catch && window.$catch === type) { if (type && type === 'TMAP') { this.initTMap() } else if (type && type === 'AMAP') { this.initAMap() } else if (type && type === 'BMAP') { this.initBMap() } } else { this.initMap() } } // 初始化地图 initMap() { const { type } = this.$options window.$catch = type this.getMapAK(type) if (type && type === 'TMAP') { this.createTMap() } else if (type && type === 'AMAP') { this.createAMap() } else if (type && type === 'BMAP') { this.createBMap() } } // 获取地图的ak getMapAK(type) { const { mapAk } = this.$options if (mapAk) { this.mapAk = mapAk } else { switch (type) { case 'TMAP': { this.mapAk = 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77' break } case 'AMAP': { this.mapAk = 'c081218aae02057742b9f1a100d6cf66' break } default: { this.mapAk = 'f7HnzEYGLgOyMyDVTh99ZEQqjlEzuhyC' } } } } // 初始化百度地图 createBMap() { const self = this const { drivingPath } = this.$options window.BMapGL_loadScriptTime = (new Date).getTime(); window.BMapGL = window.BMapGL || {}; window.BMapGL.apiLoad = function () { delete window.BMapGL.apiLoad; if (typeof self.initBMap == "function") { self.initBMap() } }; const s = document.createElement('script'); s.src = `http://api.map.baidu.com/getscript?type=webgl&v=1.0&ak=${self.mapAk}&services=&t=${(new Date).getTime()}`; document.body.appendChild(s); const link = document.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.setAttribute('href', 'http://api.map.baidu.com/res/webgl/10/bmap.css'); document.getElementsByTagName('head')[0].appendChild(link); if (drivingPath && drivingPath.length >= 2) { const trackAnim = document.createElement('script'); trackAnim.src = `//mapopen.bj.bcebos.com/github/BMapGLLib/TrackAnimation/src/TrackAnimation.min.js`; document.body.appendChild(trackAnim); } } // 初始化高德地图 createAMap() { const self = this const url = `https://webapi.amap.com/maps?v=2.0&key=${self.mapAk}&&plugin=AMap.Scale,AMap.HawkEye,AMap.ToolBar,AMap.MapType`; const jsapi = document.createElement('script'); jsapi.src = url; document.body.appendChild(jsapi); jsapi.onload = function () { self.initAMap() } } // 初始化腾讯地图 createTMap() { const self = this const url = `https://map.qq.com/api/gljs?v=1.exp&key=${self.mapAk}&libraries=geometry`; const jsapi = document.createElement('script'); jsapi.src = url; document.body.appendChild(jsapi); jsapi.onload = function () { self.initTMap() } } } //腾讯地图处理 CMap.prototype.initTMap = function () { const wd = window || {} const { id = 'map', points = [39.984104, 116.307503], zoom = 10, isScaleCtrl = false, isZoomCtrl = false, navi3DCtrl = false, drivingPath = [], enclosure = {} } = this.$options const center = new wd.TMap.LatLng(points[1], points[0]) const map = new wd.TMap.Map(document.getElementById(id), { center, //设置地图中心点坐标 zoom, //设置地图缩放级别 // pitch: 43.5, //设置俯仰角 // rotation: 45 //设置地图旋转角度 }); this.map = map // 默认是开启的-可以选择关闭 if (!isZoomCtrl) { map.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM); } /** 控件 * CONTROL_POSITION * DEFAULT_CONTROL_ID: SCALE 、FLOOR、LOGO、ROTATION、SCALE、ZOOM * **/ if (!isScaleCtrl) { map.removeControl(TMap.constants.DEFAULT_CONTROL_ID.SCALE) } if (!navi3DCtrl) { map.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ROTATION) } if (drivingPath && drivingPath.length >= 2){ let path = []; drivingPath.forEach(it => { path.push(new TMap.LatLng(it.lat, it.lng)) }) const lastPoint = drivingPath.at(-1) const startPosition = new TMap.LatLng(drivingPath[0].lat, drivingPath[0].lng); const endPosition = new TMap.LatLng(lastPoint.lat, lastPoint.lng); new TMap.MultiMarker({ // 创造MultiMarker显示起终点标记 id: 'marker-layer', map: map, styles: { start: new TMap.MarkerStyle({ width: 25, height: 35, anchor: { x: 16, y: 32 }, src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/start.png', }), end: new TMap.MarkerStyle({ width: 25, height: 35, anchor: { x: 16, y: 32 }, src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/end.png', }), }, geometries: [{ id: 'start', styleId: 'start', position: startPosition, }, { id: 'end', styleId: 'end', position: endPosition, }, ], }); // 创建 MultiPolyline显示路径折线 new TMap.MultiPolyline({ id: 'polyline-layer', map: map, styles: { style_blue: new TMap.PolylineStyle({ color: '#3777FF', width: 6, lineCap: 'round', }), }, geometries: [{ id: 'pl_1', styleId: 'style_blue', paths: path, }, ], }); setCenterAndZoom(getAreaAndCent(path)) } //多边形区域 if(enclosure && enclosure.points){ const { points, radius, strokeColor, strokeWeight } = enclosure let path = []; points.forEach(it => { path.push(new TMap.LatLng(it.lat, it.lng)) }) new TMap.MultiPolygon({ id: 'polygon-layer', //图层id map: map, //显示多边形图层的底图 styles: { //多边形的相关样式 'polygon': new TMap.PolygonStyle({ 'color': 'rgba(0,125,255,0.3)', //面填充色 'showBorder': true, //是否显示拔起面的边线 'borderColor': strokeColor || '#6699FF' //边线颜色 }) }, geometries: [{ 'id': 'polygon', //多边形图形数据的标志信息 'styleId': 'polygon', //样式id 'paths': path, //多边形的位置信息 'properties': { //多边形的属性数据 'title': 'polygon' } }] }); setCenterAndZoom(getAreaAndCent(path)) map.setCenter(path[0]) } // 圆形围栏 if (enclosure && enclosure.point){ const { point, radius, strokeColor, strokeWeight } = enclosure const TMapCent = new TMap.LatLng(point[1], point[0]) new TMap.MultiCircle({ map, styles: { // 设置圆形样式 'circle': new TMap.CircleStyle({ 'color':'rgba(41,91,255,0.3)', 'showBorder': true, 'borderColor': strokeColor || 'rgba(41,91,255,1)', 'borderWidth': strokeWeight, }), }, geometries: [{ styleId: 'circle', center: TMapCent, radius, }], }) setCenterAndZoom({distance: radius*2, cent:TMapCent}) } // 计算最大区域以及 区域中心点 function getAreaAndCent(path){ let startPoint = [], endPoint = [], rt = [], lb = []; path.forEach(it => { if(startPoint[0] === undefined || startPoint[0] < it.lat){ startPoint[0] = it.lat } if(startPoint[1] === undefined || startPoint[1] > it.lng){ startPoint[1] = it.lng } if(endPoint[0] === undefined || endPoint[0] > it.lat){ endPoint[0] = it.lat } if(endPoint[1] === undefined || endPoint[1] < it.lng){ endPoint[1] = it.lng } if(rt[0] === undefined || rt[0] < it.lat){ rt[0] = it.lat } if(rt[1] === undefined || rt[1] < it.lng){ rt[1] = it.lng } if(lb[0] === undefined || lb[0] > it.lat){ lb[0] = it.lat } if(lb[1] === undefined || lb[1] > it.lng){ lb[1] = it.lng } }) const pointSE = [ new TMap.LatLng(startPoint[0], startPoint[1]), new TMap.LatLng(endPoint[0], endPoint[1]) ] const distance = TMap.geometry.computeDistance(pointSE); var ctpath = [...pointSE, new TMap.LatLng(rt[0], rt[1]), new TMap.LatLng(lb[0], lb[1]), ]; // 使用百度地图的点位 出现报错 let cent = '' try{ cent = TMap.geometry.computeCentroid(ctpath); } catch { cent = undefined } return {distance:distance.toFixed(2), cent} } // 调整中心点和展示区域 function setCenterAndZoom(tags){ const { distance, cent } = tags console.log(distance, cent) if(cent){ console.log(2,distance, cent) map.setCenter(cent) } if (distance){ let comZoom = 10; if(distance < 80){ comZoom = 16; } else if (80 < distance && distance < 1000){ comZoom = 15; } else if (1000 < distance && distance < 3000){ comZoom = 14; } else if (3000 < distance && distance < 7000){ comZoom = 13; } else if (7000 < distance && distance < 15000){ comZoom = 12; } else { comZoom = 10; } map.setZoom(comZoom) } } } CMap.prototype.initAMap = function () { const AMap = window.AMap || {} const { id, points = [116.404, 39.915], areaName, zoom = 10, isScaleCtrl = false, isZoomCtrl = false, navi3DCtrl = false, // 添加3D控件 enclosure = {}, drivingType, drivingPath = [], } = this.$options const map = new AMap.Map(id, { center: points, resizeEnable: true, //是否监控地图容器尺寸变化 zoom }) this.map = map if (isScaleCtrl) { map.addControl(new AMap.Scale({ visible: isScaleCtrl })) } if (isZoomCtrl) { map.addControl(new AMap.ToolBar({ visible: isZoomCtrl, position: { bottom: '60px', right: '40px' } })) } if (navi3DCtrl) { map.addControl(new AMap.MapType()); } // 使用路径搜索展示 if (drivingType === 'path' && drivingPath.length > 2) { AMap.plugin(['AMap.DragRoute'], function () { let path = [] for (let i = 0; i < drivingPath.length; i++) { path.push([drivingPath[i].lng, drivingPath[i].lat]) } const route = new AMap.DragRoute(map, path, AMap.DrivingPolicy.LEAST_FEE) route.search() }); } if (drivingPath && drivingPath.length > 2) { // 折线的节点坐标数组,每个元素为 AMap.LngLat 对象 let path = [ ]; for (let i = 0; i < drivingPath.length; i++) { path.push(new AMap.LngLat(drivingPath[i].lng, drivingPath[i].lat)) } // console.log() // 创建折线实例 const polyline = new AMap.Polyline({ path: path, strokeColor: "#6699FF", strokeWeight: 6, strokeOpacity: 0.9, zIndex: 50, bubble: true, }); const startIcon = new AMap.Icon({ // 图标尺寸 size: new AMap.Size(25, 34), // 图标的取图地址 image: '//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png', // 图标所用图片大小 imageSize: new AMap.Size(135, 40), // 图标取图偏移量 imageOffset: new AMap.Pixel(-9, -3) }); // 将 开始 icon 传入 marker const startMarker = new AMap.Marker({ position: new AMap.LngLat(drivingPath[0].lng, drivingPath[0].lat), icon: startIcon, offset: new AMap.Pixel(-13, -30) }); // 创建一个 icon const endIcon = new AMap.Icon({ size: new AMap.Size(25, 34), image: '//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png', imageSize: new AMap.Size(135, 40), imageOffset: new AMap.Pixel(-95, -3) }); const endPint = drivingPath.at(-1) // 将 icon 传入 marker const endMarker = new AMap.Marker({ position: new AMap.LngLat(endPint.lng, endPint.lat), icon: endIcon, offset: new AMap.Pixel(-13, -30) }); map.add(startMarker); map.add(polyline); map.add(endMarker); map.setFitView() // 缩放地图到合适的视野级别 } // 多边形轮廓线的节点坐标数组 if (enclosure && enclosure.points) { const { points, fillColor = '#6699FF', fillOpacity = 0.3, strokeColor = '#6699FF', borderWeight = 2, } = enclosure let path = []; for (let i = 0; i < points.length; i++) { path.push(new AMap.LngLat(points[i].lng, points[i].lat)) } const polygon = new AMap.Polygon({ path: path, fillColor, // 多边形填充颜色 borderWeight, // 线条宽度,默认为 1 strokeColor, // 线条颜色 fillOpacity, // 多边形填充颜色透明度 }); map.add(polygon); map.setFitView(); } // 圆形 if (enclosure && enclosure.point) { const { point, radius, fillColor = '#6699FF', fillOpacity = 0.3, strokeColor = '#6699FF', strokeWeight = 2, } = enclosure const circle = new AMap.Circle({ center: new AMap.LngLat(point[0], point[1]), // 圆心位置 radius, // 圆半径 fillColor, // 圆形填充颜色 fillOpacity, strokeColor, // 描边颜色 strokeWeight, // 描边宽度 }); map.add(circle); map.setFitView() } } CMap.prototype.initBMap = function () { const { id, points = [116.404, 39.915], areaName, poiText = true, //是否显示POI信息 poiIcon = true, //是否显示POI图标信息 zoom = 10, drivingPath = [], enableScrollWheel = false, isScaleCtrl = false, isZoomCtrl = false, navi3DCtrl = false, // 添加3D控件 enclosure = {}, drivingType } = this.$options const map = new BMapGL.Map(id); this.map = map const point = this.$options.points && points.length === 2 ? new BMapGL.Point(points[0], points[1]) : null; map.centerAndZoom(point ?? areaName, zoom); map.enableScrollWheelZoom(enableScrollWheel); map.setDisplayOptions({ poiText, poiIcon }) // 添加3D控件 if (navi3DCtrl) { const ctrl3D = new BMapGL.NavigationControl3D(); map.addControl(ctrl3D); } // 添加比例尺控件 if (isScaleCtrl) { const scaleCtrl = new BMapGL.ScaleControl(); map.addControl(scaleCtrl); } // 添加缩放控件 if (isZoomCtrl) { const zoomCtrl = new BMapGL.ZoomControl(); map.addControl(zoomCtrl); } // 轨迹配置 if (drivingPath && drivingPath.length >= 2) { startPints = [drivingPath[0].lng, drivingPath[0].lat] endPints = [drivingPath.at(-1).lng, drivingPath.at(-1).lat] // 起始结束点位计算路径 if (drivingType && drivingType === 'path') { const start = new BMapGL.Point(...startPints); const end = new BMapGL.Point(...endPints); const driving = new BMapGL.DrivingRoute(map, { renderOptions: { map: map, autoViewport: true } }); driving.search(start, end); } else { map.centerAndZoom(new BMapGL.Point(...startPints)); let point = []; for (let i = 0; i < drivingPath.length; i++) { point.push(new BMapGL.Point(drivingPath[i].lng, drivingPath[i].lat)); } const pl = new BMapGL.Polyline(point, { strokeColor: "#6699FF", strokeWeight: 6, }); const startIcon = new BMapGL.Icon('//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png', new BMapGL.Size(23, 25)); const markerST = new BMapGL.Marker(new BMapGL.Point(...startPints), { // icon:startIcon, name: '起点', }); console.log(markerST.getIcon()) const markerEND = new BMapGL.Marker(new BMapGL.Point(...endPints), { title: '终点' }); setTimeout(function () { trackAni = new BMapGLLib.TrackAnimation(map, pl, { overallView: true, // 动画完成后自动调整视野到总览 tilt: 30, // 轨迹播放的角度,默认为55 duration: 4000, // 动画持续时长,默认为10000,单位ms delay: 300 // 动画开始的延迟,默认0,单位ms }); trackAni.start(); map.addOverlay(markerST); map.addOverlay(markerEND); }, 1000); } } // 围栏配置 if ((enclosure && enclosure.type === 'circle') || enclosure && enclosure.point) { const { fillColor = "#6699FF", fillOpacity = 0.3, strokeColor = "#6699FF", strokeWeight = 2, strokeOpacity = 1, point, radius } = enclosure const circle = new BMapGL.Circle(new BMapGL.Point(...point), radius, { fillColor, fillOpacity, strokeColor, strokeWeight, strokeOpacity, }); map.addOverlay(circle); // 添加到地图中 } else if (enclosure && enclosure.points || enclosure && enclosure.type === 'polygon') { const { fillColor = "#6699FF", fillOpacity = 0.3, strokeColor = "#6699FF", strokeWeight = 2, strokeOpacity = 1, points = [] } = enclosure let pl = [] for (let i = 0; i < points.length; i++) { pl.push(new BMapGL.Point(points[i].lng, points[i].lat)) } const polygon = new BMapGL.Polygon(pl, { fillColor, fillOpacity, strokeColor, strokeWeight, strokeOpacity }); map.addOverlay(polygon); } }