坐标系简介
WGS84:
WGS 84是全球定位系统(GPS)的基准坐标系统,广泛应用于全球定位和导航。它采用十进制度表示经度和纬度。
GCJ02:
中国国家测绘局加密坐标 , 又称为火星坐标系 , 由中国国家测绘局制定的地理坐标系统 , 在中国境内进行定位和地图制作 , 必须使用该坐标。
在中国境内 , 手机获取的 GPS 坐标 , 是 WGS 84 坐标 , 这是准确的坐标 , 但是如果想要显示在地图上的正确位置 , 需要 加入非线性随机偏差中国国家测绘局加密坐标
文档
谷歌文档
文档首页:https://developers.google.com/maps/documentation?hl=zh-cn
JSAPI文档:https://developers.google.com/maps/documentation/javascript?hl=zh-cn
JSAPI示例:https://developers.google.com/maps/documentation/javascript/examples/
高德文档
文档首页:https://lbs.amap.com/api
JSAPI文档:https://lbs.amap.com/api/javascript-api-v2/summary
JSAPI示例:https://lbs.amap.com/demo/list/js-api-v2
安装:
npm install @googlemaps/js-api-loader
npm install @amap/amap-jsapi-loader
代码:
import coordtransform from 'coordtransform'//坐标系转换,高德地图时需要转换经纬度
import { getLanguage} from "@/utils/auth";//根据语言来判断是显示高德地图还是谷歌地图
import { Loader } from '@googlemaps/js-api-loader';
import AMapLoader from "@amap/amap-jsapi-loader";
import point from '@/assets/lockIcon/point.png';
import start from '@/assets/lockIcon/start.png';
import end from '@/assets/lockIcon/end.png';
let map;
let polyline;
let polyEditor;
let markers=[];
let labelsLayer;
let infowindow;
export default {data() {return {isAmap: getLanguage() == "zh",center : getLanguage() == "zh"?[116.397428, 39.90923]:{ lat: 37.7749, lng: 116.397428 },polylineEditable:true,path: [],}},mounted() {this.loadMap();},methods: {/** 构建地图 */async loadGmap (){this.path = [];if(this.isAmap){AMapLoader.reset();await AMapLoader.load({key: 'xxx',version: '2.0',}).then(() => {map = new window.AMap.Map('map-container', {center: this.center,zoom: 15,zooms:[3,20],});map.plugin(['AMap.ToolBar','AMap.Scale','AMap.MapType'],function(){map.addControl(new window.AMap.ToolBar());map.addControl(new window.AMap.Scale());map.addControl(new window.AMap.MapType());});// 添加地图点击事件监听器if(this.isNewVersion()){map.on('click',(e) => {console.log("lat:"+e.lnglat.getLat()+",lng:"+e.lnglat.getLng());// 将点击坐标加入多边形路径if(this.polylineEditable===true){this.path.push([e.lnglat.getLng(), e.lnglat.getLat()]);}this.createLine(this.polylineEditable);console.log('点击地图回调');});}else{window.AMap.event.addListener(map, 'click', (e) => {console.log("lat:"+e.lnglat.getLat()+",lng:"+e.lnglat.getLng());// 将点击坐标加入多边形路径if(this.polylineEditable===true){this.path.push([e.lnglat.getLng(), e.lnglat.getLat()]);}this.createLine(this.polylineEditable);console.log('点击地图回调');});}console.log("加载地图成功");}).catch(e => {console.log("加载地图失败",e);});}else{const loader = new Loader({apiKey: 'xxx',version: 'weekly',language:'en-US',//libraries: ['places'] // 如果需要加载额外的库,比如 'places'});await loader.load().then(() => {map = new google.maps.Map(document.getElementById('map-container'), {center: new google.maps.LatLng(this.center.lat, this.center.lng),zoom: 15,zooms:[3,20],});});map.addListener("click", (event) => {console.log("点击前",this.path)if(this.polylineEditable===true){this.path.push(event.latLng);console.log("点击后",this.path)}this.createLine(this.polylineEditable);console.log('点击地图回调');});console.log("加载地图")}},/** 创建线条 */createLine (editable) {this.clearPolylineByMap();// 创建新的折线if(this.isAmap){polyline = new window.AMap.Polyline({path: this.path,editable: editable,draggable: false,strokeColor: "#009aff",strokeWeight: 3,strokeOpacity: 0.8,});}else{polyline = new google.maps.Polyline({path: this.path,editable: editable,draggable: editable,strokeColor: "#009aff",strokeWeight: 3,strokeOpacity: 0.8,});const googlePath = polyline.getPath();googlePath.addListener('set_at', (event) =>{console.log('Path point updated at index:', event);console.log('Updated path:', googlePath.getArray());let currPath= googlePath.getArray();this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push(currPath[i]);}console.log("设置",this.path)});googlePath.addListener('insert_at', (event) =>{console.log('Path point inserted at index:', event);console.log('Updated path:', googlePath.getArray());let currPath= googlePath.getArray();this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push(currPath[i]);}console.log("插入",this.path)});googlePath.addListener('remove_at', (event)=> {console.log('Path point removed at index:', event);console.log('Updated path:', googlePath.getArray());let currPath= googlePath.getArray();this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push(currPath[i]);}console.log("移除",this.path)});// polyline.addListener("dragend", (event) => {// let currPath= googlePath.getArray();// this.path=[];// for (let i = 0; i < currPath.length; i++) {// this.path.push(currPath[i]);// }// console.log("拖拽",this.path)// });}polyline.setMap(map);if(this.isAmap){//高德地图需要引入PolylineEditor进行编辑if(!editable){return;}map.plugin(['AMap.PolylineEditor'],()=>{polyEditor=new window.AMap.PolylineEditor(map,polyline);polyEditor._selectStyle.strokeColor="#009aff";polyEditor._selectStyle.strokeWeight=3;polyEditor._selectStyle.borderWeight=0;polyEditor.setTarget(polyline);polyEditor.open();// 编辑事件polyEditor.on('addnode',(e)=>{let currPath=polyline.getPath();console.log("添加"+currPath)this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push([currPath[i].lng, currPath[i].lat]);}});// 编辑事件polyEditor.on('removenode',(e)=>{let currPath=polyline.getPath();console.log("移除"+currPath)this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push([currPath[i].lng, currPath[i].lat]);}});// 编辑事件polyEditor.on('adjust',(e)=>{let currPath=polyline.getPath();console.log("移动"+currPath)this.path=[];for (let i = 0; i < currPath.length; i++) {this.path.push([currPath[i].lng, currPath[i].lat]);}});});}console.log("创建线条完成");},/** 闭合 */closePolyline () {if (this.path.length < 3) {// this.$modal.msgError(this.$t('area.lt3potion'));return;}// 判断路径是否闭合if (this.path[0]==this.path[this.path.length - 1]) {return;}// 添加最后一个点,使路径闭合this.path.push(this.path[0]);this.createLine(true);},/** 清除 */clearPolylineAndPath (){// 清除之前的折线this.path = [];this.clearPolylineByMap();},clearPolylineByMap(){// 移除折线if (polyline) {polyline.setMap(null);}if (polyEditor) {polyEditor.setTarget(null);polyEditor.close();}},/** 根据后台接口经纬度数据显示线条在地图上 */showPolyline (val,editable) {if (val == null || val == "") {return}this.saveId = val.id;if (val.detail == null || val.detail == "" ||!Array.isArray(val.detail) || val.detail.length==0) {return}this.polylineEditable=editable;// 清除之前的折线this.clearPolylineAndPath();// currAreaColor=val.color;let latLngs = [];for (let i = 0; i < val.detail.length; i++) {if(this.isAmap){let gcj02=coordtransform.wgs84togcj02(val.detail[i].lng, val.detail[i].lat);//将坐标系转成高德坐标系latLngs.push({lng:gcj02[0],lat:gcj02[1]});}else{latLngs.push(val.detail[i]);}}for (let i = 0; i < latLngs.length; i++) {if(this.isAmap){this.path.push([latLngs[i].lng, latLngs[i].lat]);}else{this.path.push(new google.maps.LatLng(latLngs[i].lat, latLngs[i].lng))}}this.createLine(editable);this.showMarker(latLngs);if(this.isAmap){map.setFitView();//根据图形自适应缩放级别}else{if(this.path.length>0){var bounds = new google.maps.LatLngBounds(); //声明一个boundsfor(let i=0;i<latLngs.length;i++){bounds.extend(new google.maps.LatLng(latLngs[i].lat, latLngs[i].lng));}map.fitBounds(bounds);//根据图形自适应缩放级别}}},/** 将地图上线条的经纬度数据保存到数据库 */savePolyline() {this.closePolyline();let reqPath = [];//转换数据for (let i = 0; i < this.path.length; i++) {if (this.isAmap) {reqPath.push({lng: this.path[i][0],lat: this.path[i][1]});} else {reqPath.push({lat: this.path[i].lat(),lng: this.path[i].lng()});}}if(reqPath.length<=0){return;}let latLngs= [];for (let i = 0; i < reqPath.length; i++) {if(this.isAmap){let wgs84 = coordtransform.gcj02towgs84(reqPath[i].lng, reqPath[i].lat);//将坐标系还原成GPS通用坐标系latLngs.push({lng: wgs84[0],lat: wgs84[1]});}else{latLngs.push(reqPath[i]);}}updateLatLngs({id:1,latLngs:latLngs}).then(() => {this.$modal.msgSuccess(this.$t('common.updateSuccess'));this.getList();}).finally(() => {this.buttonLoading = false;});},showMarker(data) {if(this.isAmap){console.log("加载点:"+data.length);if (markers && markers.length > 0) {labelsLayer.remove(markers);markers = []}if (data && data.length > 0) {const icon = {type: 'image', // 图标类型,现阶段只支持 image 类型image: point, // 图片 urlsize: [25, 25], // 图片尺寸anchor: 'center' // 图片相对 position 的锚点,默认为 bottom-center};for (let i = 0; i < data.length; i++) {if (data[i].lng && data[i].lat && !(data[i].lng == 0 && data[i].lat == 0)) {data[i].num = i + 1;let marker = new window.AMap.LabelMarker({position: [data[i].lng, data[i].lat],icon: icon,data: data[i],zIndex: 101});marker.on('click', this.markerClick);markers.push(marker);}}// console.log(markers);if (data.length >= 2) {const iconStart = {type: 'image', // 图标类型,现阶段只支持 image 类型image: start, // 图片 urlsize: [30, 33], // 图片尺寸offset: [0, -16.5],anchor: 'center' // 图片相对 position 的锚点,默认为 bottom-center};const iconEnd = {type: 'image', // 图标类型,现阶段只支持 image 类型image: end, // 图片 urloffset: [0, -16.5],size: [30, 33], // 图片尺寸anchor: 'center' // 图片相对 position 的锚点,默认为 bottom-center};let markerStart = new window.AMap.LabelMarker({position: [data[0].lng, data[0].lat],//position:[route.query.startLng,route.query.startLat],icon: iconStart,data: data[0],zIndex: 102});let markerEnd = new window.AMap.LabelMarker({position: [data[data.length - 1].lng, data[data.length - 1].lat],//position:[route.query.endLng,route.query.endLat],icon: iconEnd,data: data[data.length - 1],zIndex: 103});markerStart.on('click', this.markerClick);markerEnd.on('click', this.markerClick);markers.push(markerStart);markers.push(markerEnd);}labelsLayer.add(markers);}}else{if (markers && markers.length > 0) {map.remove(markers);}for (let i = 0; i < data.length; i++) {if (data[i].lng && data[i].lat && !(data[i].lng == 0 && data[i].lat == 0)) {data[i].num = i + 1let marker = new google.maps.Marker({position: {lat: data[i].lat, lng: data[i].lng},icon: {url: point,size: new google.maps.Size(28, 28),anchor: new google.maps.Point(14, 14)},zIndex: 101,map: map});markers.push(marker);google.maps.event.addListener(marker, 'click', () => {this.markerClick(null,marker, data[i])});}}if (data.length >= 2) {let markerStart = new google.maps.Marker({position: {lat: data[0].lat, lng: data[0].lng},icon: {url: start,size: new google.maps.Size(60, 66),scaledSize: new google.maps.Size(30, 33),anchor: new google.maps.Point(15, 16.5)},zIndex: 102,map: map});let markerEnd = new google.maps.Marker({position: {lat: data[data.length - 1].lat, lng: data[data.length - 1].lng},icon: {url: end,size: new google.maps.Size(60, 66),scaledSize: new google.maps.Size(30, 33),anchor: new google.maps.Point(15, 16.5)},zIndex: 103,map: map});google.maps.event.addListener(markerStart, 'click', () => {this.markerClick(null,markerStart, data[0])});google.maps.event.addListener(markerEnd, 'click', () => {this.markerClick(null,markerEnd, data[data.length - 1])});markers.push(markerStart);markers.push(markerEnd);}}},async markerClick (e,marker, data){if(this.isAmap){data = e.target._originOpts.data;}let template =`<div style='font-size: 15px'><p style='margin-left: 10px'>No.` + data.num + `</p> <p style='margin-left: 10px'>` + this.$t('map.longitude') + `:` + data.lng + `</p><p style='margin-left: 10px'>` + this.$t('map.latitude') + `:` + data.lat + `</p><p style='margin-left: 10px'>` + this.$t('map.gps_time') + `:` + this.parseTime(data.positionTime, '{y}/{m}/{d} {h}:{i}:{s}') + `</p></div>`;if(this.isAmap){infowindow = new window.AMap.InfoWindow({content: template});infowindow .open(map, e.lnglat);}else{infowindow.setContent(template);infowindow.open(map, marker);}},}
}