openlayers 地图组件封装

编程入门 行业动态 更新时间:2024-10-26 09:22:19

openlayers 地图<a href=https://www.elefans.com/category/jswz/34/1771375.html style=组件封装"/>

openlayers 地图组件封装

openlayers 地图组件封装

<template><div class="mapBox"><!-- 地图 --><div ref="map" id="map" class="map"></div><!-- 点位弹窗 --><div id="popup" class="ol-popup"><a href="#" id="popup-closer" class="ol-popup-closer"></a><div id="popup-content">{{ popup.content }}</div></div><!-- 地图操作 --><div v-if="false" class="optionsBox"><!-- GIS服务 --><el-dropdown @command="handleGisCommand"><el-button type="primary">GIS服务<i class="el-icon-arrow-down el-icon--right"></i></el-button><el-dropdown-menu slot="dropdown"><el-dropdown-item command="1">测距离</el-dropdown-item><el-dropdown-item command="2">测面积</el-dropdown-item><el-dropdown-item command="3">清空</el-dropdown-item><el-dropdown-item command="4">打印地图</el-dropdown-item></el-dropdown-menu></el-dropdown><!-- 矢量底图 / 卫星底图 --><el-radio-group v-model="checkUnderLayer" @change="handleUnderLayerChange"><el-radio-button label="sldt">矢量底图</el-radio-button><el-radio-button label="wxdt">卫星底图</el-radio-button></el-radio-group><!-- 注记层 / 行政区划 --><el-checkbox-group v-model="checkLayers" @change="handleLayerChange"><el-checkbox-button label="zjc">注记层</el-checkbox-button><el-checkbox-button label="xzqh">行政区划</el-checkbox-button></el-checkbox-group><!-- 全屏 --><el-button type="primary" @click="handleFullScreen">{{ isFullScreen ? "退出全屏" : "全屏" }}</el-button><!-- 回到原点 --><el-button type="primary" @click="handleBackCenter">回到原点</el-button><!-- 轨迹运动 --><el-button type="primary" @click="handleTrackStart">{{ mapTrack.isPlay ? "暂停" : "开始" }}</el-button><el-button type="primary" @click="handleTrackStop">停止</el-button></div></div>
</template><script>
import "ol/ol.css";
import request from "@/utils/request.js";
import domtoimage from "dom-to-image";
import Text from "ol/style/Text";import { getWidth, getTopLeft } from "ol/extent";
import View from "ol/View";
import Map from "ol/Map";
import WMTSTileGrid from "ol/tilegrid/WMTS";
import Feature from "ol/Feature";
import { WMTS, Vector as VectorSource, XYZ } from "ol/source";
import { Tile as TileLayer, Vector as VectorLayer, VectorImage } from "ol/layer";
import { getArea, getLength } from "ol/sphere";
import { unByKey } from "ol/Observable";
import { LineString, Polygon, Point, MultiLineString } from "ol/geom";
import { MousePosition, ScaleLine, ZoomSlider } from "ol/control";
import { createStringXY } from "ol/coordinate";
import * as olProj from "ol/proj";
import { Draw, Select, Modify } from "ol/interaction";
import Overlay from "ol/Overlay";import { Circle as CircleStyle, Fill, Stroke, Style, Icon } from "ol/style";
import { scale } from "ol/size";import GeoJSON from "ol/format/GeoJSON";
import SourceVector from "ol/source/Vector";
import { getDistance } from "ol/sphere";import { getVectorContext } from "ol/render";
import { EventBus } from "@/utils/eventBus.js";import { transform, fromLonLat, toLonLat } from "ol/proj";import LayerTile from "ol/layer/Tile";
import ImageLayer from "ol/layer/Image";
import { Raster as RasterSource } from "ol/source";
import { defaults as defaultControls } from "ol/control";
import { saveAs } from "file-saver";
export default {data() {return {map: null,mapCenter: [118.091838, 36.958653], // 地图中心点// 弹窗popup: {popupOverlay: null, // 点位弹窗content: "", // 弹窗显示内容},// 行政区划/注记层checkLayers: ["zjc", "xzqh"],mapLayers: {},// 底图underlayer: {sldt: { layer: null, show: true },wxdt: { layer: null, show: false },},checkUnderLayer: "sldt",// 测量距离/面积mapDraw: {helpTooltipElement: null,feature: null,helpTooltip: null,draw: null,measureTooltipElement: null,measureTooltip: null,listener: null,mapMouseMove: null,drawElements: [],drawLayers: [],},isFullScreen: false,// 轨迹mapTrack: {isPlay: false, // 开始或暂停运动isStop: false, // 停止运动, 复位route: null,featureMove: {},geometryMove: {},carPoints: [], //车还要走的点routeIndex: 0, //当前小车所在的路段timer: null,routeLayer: {},coordinates: [[117.98804853292008, 36.924719974587475],... ...],},};},mounted() {// this.initMap();this.initDeepColorMap();// this.initBlueColorMap();this.initEvent();this.initPointPopup();// 添加轨迹// this.addTrack();// 监听全屏状态window.addEventListener("resize", () => {// 是否全屏this.isFullScreen =document.fullscreenElement ||document.webkitFullscreenElement ||document.msFullscreenElement ||document.mozFullScreenElement ||null;});},methods: {handleTrackStart() {this.mapTrack.isPlay = !this.mapTrack.isPlay;if (this.mapTrack.isPlay) {//开始动this.trackMoveStart();} else {this.trackMovePause();}},handleTrackStop() {this.mapTrack.isPlay = false;this.mapTrack.isStop = true;this.resetTrack();this.addTrack();},/*** 切换底图*/handleUnderLayerChange(type) {for (let i in this.underlayer) {this.underlayer[i].layer.setVisible(false);this.underlayer[i].show = false;}this.underlayer[type].show = true;this.underlayer[type].layer.setVisible(true);},/*** 注记层/行政区划 显示与隐藏*/handleLayerChange() {for (let i in this.mapLayers) {this.mapLayers[i].layer.setVisible(false);}for (let i in this.checkLayers) {this.mapLayers[this.checkLayers[i]].layer.setVisible(true);}},/*** 切换全屏*/handleFullScreen() {if (this.isFullScreen) {this.exitfullscreen();} else {this.enterfullscreen();}},/*** 回到原点*/handleBackCenter() {this.map.getView().setCenter(this.mapCenter);},/*** 初始化地图*/initMap() {// 天地图图层const tdLayer = new TileLayer({source: new XYZ({crossOrigin: "anonymous",projection: "EPSG:4326",url: "={x}&y={y}&l={z}&T=vec_c&tk=地图的key",}),className: "dt",});// 天地图文字图层const tdTextLayer = new TileLayer({source: new XYZ({crossOrigin: "anonymous",projection: "EPSG:4326",url: "={x}&y={y}&l={z}&T=cva_c&tk=地图的key",}),className: "txt",});this.map = new Map({target: "map",view: new View({center: this.mapCenter,projection: olProj.get("EPSG:4326"),zoom: 13,maxZoom: 17,minZoom: 1,}),});this.map.addLayer(tdLayer);this.map.addLayer(tdTextLayer);this.mapLayers.zjc = { layer: tdTextLayer, show: true };//卫星影像图层const projection = olProj.get("EPSG:4326");const projectionExtent = projection.getExtent();const size = getWidth(projectionExtent) / 256;const resolutions = [];const matrixIds = [];for (let z = 0; z < 20; ++z) {resolutions[z] = size / Math.pow(2, z + 1);matrixIds[z] = z + 1;}const tdwxLayer = new TileLayer({opacity: 1,visible: false,source: new WMTS({crossOrigin: "anonymous",url: "=img_w&x={x}&y={y}&l={z}&tk=地图的key",layer: "wxt",matrixSet: "c",format: "tiles",style: "default",projection: this.projection,tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: matrixIds,}),wrapX: true,}),});this.map.addLayer(tdwxLayer);this.underlayer.sldt = { layer: tdLayer, show: true };this.underlayer.wxdt = { layer: tdwxLayer, show: false };},/*** 初始化深颜色地图*/initDeepColorMap() {const view = new View({center: this.mapCenter,zoom: 12, //图层缩放大小projection: "EPSG:4326",});this.map = new Map({target: "map",view: view,controls: defaultControls({zoom: true,attribution: false,rotate: false,}),});// 添加矢量底图let url = "={x}&y={y}&l={z}";url = `${url}&T=vec_c&tk=地图的key`;const source = new XYZ({crossOrigin: "anonymous",url: url,projection: "EPSG:4326",});const tdtLayer = new TileLayer({className: "blueLayer",source: source,});this.map.addLayer(tdtLayer);// 添加矢量注记url = "={x}&y={y}&l={z}";url = `${url}&T=cva_c&tk=地图的key`;const sourceCVA = new XYZ({crossOrigin: "anonymous",url: url,projection: "EPSG:4326",});const tdtcvaLayer = new TileLayer({className: "blueLayer",source: sourceCVA,});this.map.addLayer(tdtcvaLayer);this.mapLayers.zjc = { layer: tdtcvaLayer, show: true };//卫星影像图层const projection = olProj.get("EPSG:4326");const projectionExtent = projection.getExtent();const size = getWidth(projectionExtent) / 256;const resolutions = [];const matrixIds = [];for (let z = 0; z < 20; ++z) {resolutions[z] = size / Math.pow(2, z + 1);matrixIds[z] = z + 1;}const tdwxLayer = new TileLayer({opacity: 1,visible: false,source: new WMTS({crossOrigin: "anonymous",url:"=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=地图的key",layer: "wxt",matrixSet: "c",format: "tiles",style: "default",projection: this.projection,tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: matrixIds,}),wrapX: true,}),});this.map.addLayer(tdwxLayer);this.underlayer.sldt = { layer: tdtLayer, show: true };this.underlayer.wxdt = { layer: tdwxLayer, show: false };},initBlueColorMap() {let target = "map";let tileLayer = [new TileLayer({source: new XYZ({url: "/{z}/{y}/{x}",}),}),];let view = new View({center: this.mapCenter,zoom: 12,});this.map = new Map({target: target,layers: tileLayer,view: view,});const TiandiMap_cia = new TileLayer({name: "天地图影像注记图层",source: new XYZ({url: "=cia_w&x={x}&y={y}&l={z}&tk=地图的key", //parent.TiandituKey()为天地图密钥wrapX: false,}),});// 添加到地图上this.map.addLayer(TiandiMap_cia);},/*** 地图事件*/initEvent() {// 地图加载完成this.map.once("rendercomplete", () => {// 行政区划this.addProvinceBorder();// 添加点位//this.addPoint([[118.103288, 36.96607]], require("@/assets/image/homecar2.png"), -(Math.PI / 3));this.$emit("complete", this.map);});// 地图点击this.map.on("click", e => {// 点位弹窗var pixel = this.map.getEventPixel(e.originalEvent);console.log(e.coordinate);let feature = this.map.forEachFeatureAtPixel(pixel, feature => {return feature;});if (feature && feature.name && feature.name != "cityScope") {var coodinate = e.coordinate;this.popup.content = "你点击的坐标为:" + coodinate;this.popup.popupOverlay.setPosition(coodinate);this.map.addOverlay(this.popup.popupOverlay);this.$emit("pointClick", true, feature.name, e.coordinate, e.pixel);} else {this.$emit("pointClick", false, feature.name, e.coordinate, e.pixel);this.popup.popupOverlay.setPosition(undefined);}});},/*** 初始化点位弹窗*/initPointPopup() {var container = document.getElementById("popup");var popupCloser = document.getElementById("popup-closer");this.popup.popupOverlay = new Overlay({element: container,autoPan: true,});popupCloser.addEventListener("click", function() {this.popup.popupOverlay.setPosition(undefined);});},/**** 加行政区域边界* 获取geojson数据地址: */addProvinceBorder(geojson) {//行政区划边界图层const provinceLayer = new VectorLayer({renderMode: "vector",source: new VectorSource(),zIndex: 0,});this.map.addLayer(provinceLayer);this.mapLayers.xzqh = { layer: provinceLayer, show: true };// 加载geojsonlet qxn = geojson ? geojson : require("../mixins/370321.json");qxn.features.forEach(featureJSON => {let feature = new GeoJSON().readFeature(featureJSON);feature.set("name", feature.values_.NAME);feature.setStyle(new Style({stroke: new Stroke({//边框color: "rgba(3,15,83, 1)",width: 1,}),fill: new Fill({//填充color: "rgba(3,15,83, 0.5)", // "rgba(255, 255, 255, 0.5)"}),}));provinceLayer.getSource().addFeature(feature);});},/*** 添加点位* @param {*} list [[经度, 纬度], [经度, 纬度]]* @param {*} icon 点位图标图片路径* @param {*} angle 旋转角度* @param {*} popupType 弹窗类型  可以在template中自定义多种弹窗, 然后指定弹出哪个*/addPoint(list, icon, angle, popupType = 0) {// 设置图层const flagLayer = new VectorLayer({source: new VectorSource(),});// 添加图层this.map.addLayer(flagLayer);let featuresArr = [];// 循环添加featurefor (let i = 0; i < list.length; i++) {// 创建feature,一个feature就是一个点坐标信息let feature = new Feature({geometry: new Point([list[i][0], list[i][1]]),});feature.name = "point";feature.popupType = popupType;// 设置要素的图标feature.setStyle(new Style({// 设置图片效果image: new Icon({src: icon,anchor: [0.5, 0.9],scale: 1,rotation: angle || 0,}),zIndex: 6000,}));// feature.setStyle(//   new Style({//     // 设置图片效果//     image: new CircleStyle({//       radius: 10,//       stroke: new Stroke({//         color: '#fff'//       }),//       fill: new Fill({//         color: '#3399cc'//       })//     }),//     zIndex: 3000,//     name: '1111'//   }),// );featuresArr.push(feature);} // for 结束// 批量添加featureflagLayer.getSource().addFeatures(featuresArr);}, gishandleGisCommand(cmd) {switch (cmd) {case "1":this.drawDistance();break;case "2":this.drawArea();break;case "3":this.drawClear();break;case "4":this.printMap();break;default:break;}},/*** 测距离*/drawDistance() {let source = new VectorSource(); // 首先创建一个数据源,用来放置绘制过程中和绘制结束后的线段const layer = new VectorLayer({// 添加一个图层,用来放置数据源,样式自己随便设置就可以了,我这里默认的官网source: source,style: new Style({fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),stroke: new Stroke({color: "#ffcc33",width: 4,}),image: new CircleStyle({radius: 7,fill: new Fill({color: "#ffcc33",}),}),}),zIndex: 4000,});this.mapDraw.mapMouseMove = this.map.on("pointermove", ev => {// 给地图添加一个鼠标移动事件let helpMsg = "点击开始测量"; // 默认开始的操作提示文本if (this.mapDraw.feature) {// featuer 是全局的,判断有没有点击鼠标绘制过helpMsg = "双击结束测量"; // 如果之前点击绘制了就显示双击结束}this.mapDraw.helpTooltipElement.innerHTML = helpMsg; // 设置dom的提示文字this.mapDraw.helpTooltip.setPosition(ev.coordinate); // 设置位置跟着鼠标走this.mapDraw.helpTooltipElement.classList.remove("hidden"); // 让他显示出来});this.drawCreateHelpTooltip(); // 创建那个helpTooltipElement方法this.map.addLayer(layer); // 把图层添加到地图this.mapDraw.drawLayers.push(layer); // 保存起来// 开始绘制线this.mapDraw.draw = new Draw({source: source,type: "LineString", // 绘制线style: new Style({// 绘制完成之前线的样式,这是官网的样式,需要的话自己可以修改成自己想要的样子fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),stroke: new Stroke({color: "rgba(0, 0, 0, 0.5)",lineDash: [10, 10],width: 4,}),image: new CircleStyle({radius: 5,stroke: new Stroke({color: "rgba(0, 0, 0, 0.7)",}),fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),}),}),});this.map.addInteraction(this.mapDraw.draw); // draw 绑定到地图上面去// 格式化长度, 直接官网代码const formatLength = function(line) {const length = getLength(line);let output;if (length > 100) {output = Math.round((length / 1000) * 100) / 100 + " " + "km";} else {output = Math.round(length * 100) / 100 + " " + "m";}return output;};this.drawCreateMeasureTooltip(); // 创建那个距离的提示框// 开始监听绘制const _this = this;this.mapDraw.draw.on("drawstart", evt => {_this.mapDraw.feature = evt.feature; // feature就是全局的let tooltipCoord = evt.coordinate; // 鼠标当前的位置_this.mapDraw.listener = _this.mapDraw.feature.getGeometry().on("change", function(evt) {const geom = evt.target;let output = formatLength(geom); // 距离的格式tooltipCoord = geom.getLastCoordinate(); // 设置鼠标位置改变后的实时位置_this.mapDraw.measureTooltipElement.innerHTML = output; // 设置提示框的内容,就是距离_this.mapDraw.measureTooltip.setPosition(tooltipCoord); // 设置距离提示框的位置});});// 双击绘制完成this.mapDraw.draw.on("drawend", () => {this.mapDraw.measureTooltipElement.className = "ol-tooltip ol-tooltip-static";this.mapDraw.measureTooltip.setOffset([0, -7]);this.mapDraw.feature = null;this.mapDraw.measureTooltipElement = null;this.drawCreateMeasureTooltip();unByKey(this.mapDraw.listener);// 画完一次就终止(不连续画线)unByKey(this.mapDraw.mapMouseMove);setTimeout(() => {this.mapDraw.helpTooltipElement.classList.add("hidden");this.mapDraw.helpTooltipElement = null;this.map.removeInteraction(this.mapDraw.draw);}, 50);});},/*** 测距离提示信息*/drawCreateHelpTooltip() {if (this.mapDraw.helpTooltipElement) {this.mapDraw.helpTooltipElement.parentNode.removeChild(this.mapDraw.helpTooltipElement);}this.mapDraw.helpTooltipElement = document.createElement("div");this.mapDraw.helpTooltipElement.className = "ol-tooltip hidden";this.mapDraw.helpTooltip = new Overlay({element: this.mapDraw.helpTooltipElement,offset: [15, 0],positioning: "center-left",});this.map.addOverlay(this.mapDraw.helpTooltip);},/*** 测距离提示信息*/drawCreateMeasureTooltip() {if (this.mapDraw.measureTooltipElement) {this.mapDraw.measureTooltipElement.parentNode.removeChild(this.mapDraw.measureTooltipElement);}this.mapDraw.measureTooltipElement = document.createElement("div");this.mapDraw.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";this.mapDraw.measureTooltip = new Overlay({element: this.mapDraw.measureTooltipElement,offset: [0, -15],positioning: "bottom-center",stopEvent: false,insertFirst: false,});this.mapDraw.drawElements.push(this.mapDraw.measureTooltip);this.map.addOverlay(this.mapDraw.measureTooltip);},/*** 清空绘制*/drawClear() {for (let i = 0; i < this.mapDraw.drawLayers.length; i++) {this.map.removeLayer(this.mapDraw.drawLayers[i]);}for (let i = 0; i < this.mapDraw.drawElements.length; i++) {this.map.removeOverlay(this.mapDraw.drawElements[i]);}this.mapDraw.drawLayers = [];this.mapDraw.drawElements = [];this.map.removeInteraction(this.mapDraw.draw);unByKey(this.mapDraw.mapMouseMove);},/// 测面积drawArea() {let source = new VectorSource(); // 首先创建一个数据源,用来放置绘制过程中和绘制结束后的线段const layer = new VectorLayer({// 添加一个图层,用来放置数据源,样式自己随便设置就可以了,我这里默认的官网source: source,style: new Style({fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),stroke: new Stroke({color: "#ffcc33",width: 4,}),image: new CircleStyle({radius: 7,fill: new Fill({color: "#ffcc33",}),}),}),zIndex: 4000,});this.mapDraw.mapMouseMove = this.map.on("pointermove", ev => {// 给地图添加一个鼠标移动事件let helpMsg = "点击开始测量"; // 默认开始的操作提示文本if (this.mapDraw.feature) {// featuer 是全局的,判断有没有点击鼠标绘制过helpMsg = "双击结束测量"; // 如果之前点击绘制了就显示双击结束}this.mapDraw.helpTooltipElement.innerHTML = helpMsg; // 设置dom的提示文字this.mapDraw.helpTooltip.setPosition(ev.coordinate); // 设置位置跟着鼠标走this.mapDraw.helpTooltipElement.classList.remove("hidden"); // 让他显示出来});this.drawCreateHelpTooltip(); // 创建那个helpTooltipElement方法this.map.addLayer(layer); // 把图层添加到地图this.mapDraw.drawLayers.push(layer); // 保存起来// 开始绘制线this.mapDraw.draw = new Draw({source: source,type: "Polygon", // 绘制线style: new Style({// 绘制完成之前线的样式,这是官网的样式,需要的话自己可以修改成自己想要的样子fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),stroke: new Stroke({color: "rgba(0, 0, 0, 0.5)",lineDash: [10, 10],width: 4,}),image: new CircleStyle({radius: 5,stroke: new Stroke({color: "rgba(0, 0, 0, 0.7)",}),fill: new Fill({color: "rgba(255, 255, 255, 0.2)",}),}),}),});this.map.addInteraction(this.mapDraw.draw); // draw 绑定到地图上面去const _this = this;// 面积测量函数const formatArea = function(polygon) {var sourceProj = _this.map.getView().getProjection(); // 获取投影坐标系var area = getArea(polygon, {projection: sourceProj,});var output;if (area > 10000) {output = Math.round((area / 1000000) * 100) / 100 + " " + "km<sup>2</sup>";} else {output = Math.round(area * 100) / 100 + " " + "m<sup>2</sup>";}return output;};this.drawCreateMeasureTooltip(); // 创建那个距离的提示框// 开始监听绘制this.mapDraw.draw.on("drawstart", evt => {_this.mapDraw.feature = evt.feature; // feature就是全局的let tooltipCoord = evt.coordinate; // 鼠标当前的位置_this.mapDraw.listener = _this.mapDraw.feature.getGeometry().on("change", function(evt) {const geom = evt.target;let output = formatArea(geom); // 距离的格式tooltipCoord = geom.getInteriorPoint().getCoordinates(); // 设置鼠标位置改变后的实时位置_this.mapDraw.measureTooltipElement.innerHTML = output; // 设置提示框的内容,就是距离_this.mapDraw.measureTooltip.setPosition(tooltipCoord); // 设置距离提示框的位置});});// 双击绘制完成this.mapDraw.draw.on("drawend", () => {this.mapDraw.measureTooltipElement.className = "ol-tooltip ol-tooltip-static";this.mapDraw.measureTooltip.setOffset([0, -7]);this.mapDraw.feature = null;this.mapDraw.measureTooltipElement = null;this.drawCreateMeasureTooltip();unByKey(this.mapDraw.listener);// 画完一次就终止(不连续画线)unByKey(this.mapDraw.mapMouseMove);setTimeout(() => {this.mapDraw.helpTooltipElement.classList.add("hidden");this.mapDraw.helpTooltipElement = null;this.map.removeInteraction(this.mapDraw.draw);}, 50);});},/*** 打印地图(将地图保存为图片)*/printMap() {const that = this;let exportOptions = {filter: function(element) {var className = element.className || "";return (className.indexOf("ol-control") === -1 ||className.indexOf("ol-scale") > -1 ||(className.indexOf("ol-attribution") > -1 && className.indexOf("ol-uncollapsible")));},};that.map.once("rendercomplete", function(e) {// exportOptions.width = 1000;// exportOptions.height = 800;domtoimage.toJpeg(that.map.getViewport(), exportOptions).then(function(dataUrl) {saveAs(dataUrl, "map.jpg");});});that.map.updateSize();}, gis end/ 全屏enterfullscreen() {//进入全屏let docElm = document.documentElement;//FireFoxif (docElm.mozRequestFullScreen) {docElm.mozRequestFullScreen();}//Chrome等else if (docElm.webkitRequestFullScreen) {docElm.webkitRequestFullScreen();}//IE11else if (elem.msRequestFullscreen) {elem.msRequestFullscreen();}this.isFullScreen = true;},exitfullscreen() {//退出全屏if (document.mozCancelFullScreen) {document.mozCancelFullScreen();} else if (document.webkitCancelFullScreen) {document.webkitCancelFullScreen();} else if (document.msExitFullscreen) {document.msExitFullscreen();}this.isFullScreen = false;}, 全屏 end/// 轨迹回放,  轨迹运动//轨迹线addTrack() {this.mapTrack.route = new LineString(this.mapTrack.coordinates);this.mapTrack.geometryMove = new Point(this.mapTrack.route.getFirstCoordinate());this.mapTrack.featureMove = new Feature({type: "featureMove",geometry: this.mapTrack.geometryMove,});this.mapTrack.featureMove.name = "track_point";//坐标转换this.mapTrack.dotsData = this.mapTrack.coordinates.map(item => {return transform(item, "EPSG:3857", "EPSG:4326");});//深复制车的位置,不在原数组改变,方便重新播放// this.carPoints = JSON.parse(JSON.stringify(this.dotsData));this.mapTrack.carPoints = [...this.mapTrack.dotsData];this.mapTrack.routeLayer = new VectorLayer({source: new VectorSource({features: [new Feature({type: "route",geometry: this.mapTrack.route,}),this.mapTrack.featureMove,new Feature({type: "startIcon",geometry: new Point(this.mapTrack.route.getFirstCoordinate()),}),new Feature({type: "endIcon",geometry: new Point(this.mapTrack.route.getLastCoordinate()),}),new Feature({type: "featureMove",geometry: new Point(this.mapTrack.carPoints[0]),}),],}),style: feature => {if (feature.get("type") == "route") {return new Style({stroke: new Stroke({width: 6,color: [25, 59, 128, 1],}),});} else if (feature.get("type") == "startIcon") {return new Style({// image: new Icon({// 	anchor: [0.5, 1],// 	src: "",// 	// src: require("@/assets/image/map_start.png"),// 	// src: require("@/assets/image/homecar2.png"),// 	scale: 1, //设置大小// }),});} else if (feature.get("type") == "endIcon") {return new Style({// image: new Icon({// 	anchor: [0.5, 1],// 	src: "",// 	// src: require("@/assets/image/map_end.png"),// 	// src: require("@/assets/image/homecar2.png"),// 	scale: 1, //设置大小// }),});} else if (feature.get("type") == "featureMove") {return new Style({image: new Icon({//	src: ".6.5/examples/data/icon.png",// src: require("@/assets/image/map_arrow.png"),src: require("@/assets/image/homecar2.png"),scale: 1,//anchor: [0.5, 0.5],rotation: this.trackCountRotate(),}),});}//return this.mapTrack.styles[feature.get("type")];},});this.map.addLayer(this.mapTrack.routeLayer);},/*** 小车开始运动*/trackMoveStart() {this.mapTrack.timer = setInterval(() => {if (this.mapTrack.routeIndex + 1 >= this.mapTrack.carPoints.length) {//重头开始this.mapTrack.routeIndex = 0;//移除要素// this.mapTrack.routeLayer.getSource().removeFeature(this.mapTrack.featureMove);clearInterval(this.mapTrack.timer);//重复运动// this.addTrack();// this.trackMoveStart();//this.open(); //自动开启功能return;}//到转折点旋转角度if (this.trackNextPoint() === this.mapTrack.carPoints[this.mapTrack.routeIndex + 1]) {this.mapTrack.routeIndex++;if (this.mapTrack.featureMove.getStyle()) {this.mapTrack.featureMove.getStyle().getImage().setRotation(this.trackCountRotate());}}//改变坐标点this.mapTrack.featureMove.getGeometry().setCoordinates(fromLonLat(this.mapTrack.carPoints[this.mapTrack.routeIndex]));// 经过的点位console.log(this.mapTrack.coordinates[this.mapTrack.routeIndex]);}, 10);},/*** 小车暂停运动*/trackMovePause() {clearInterval(this.mapTrack.timer);},//计算下一个点的位置//这里的算法是计算了两点之间的点   两点之间的连线可能存在很多个计算出来的点trackNextPoint() {let routeIndex = this.mapTrack.routeIndex;let p1 = this.map.getPixelFromCoordinate(fromLonLat(this.mapTrack.carPoints[routeIndex])); //获取在屏幕的像素位置let p2 = this.map.getPixelFromCoordinate(fromLonLat(this.mapTrack.carPoints[routeIndex + 1]));let dx = p2[0] - p1[0];let dy = p2[1] - p1[1];//打印可见  在没有走到下一个点之前,下一个点是不变的,前一个点以这个点为终点向其靠近let distance = Math.sqrt(dx * dx + dy * dy);if (distance <= 1) {return this.mapTrack.carPoints[routeIndex + 1];} else {let x = p1[0] + dx / distance;let y = p1[1] + dy / distance;let coor = transform(this.map.getCoordinateFromPixel([x, y]), "EPSG:3857", "EPSG:4326");this.mapTrack.carPoints[routeIndex] = coor; //这里会将前一个点重新赋值  要素利用这个坐标变化进行移动return this.mapTrack.carPoints[routeIndex];}},//计算两点之间的角度  算旋转角度trackCountRotate() {let i = this.mapTrack.routeIndex,j = i + 1;if (j === this.mapTrack.carPoints.length) {i--;j--;}let p1 = this.mapTrack.carPoints[i];let p2 = this.mapTrack.carPoints[j];return Math.atan2(p2[0] - p1[0], p2[1] - p1[1]);},resetTrack() {clearInterval(this.mapTrack.timer);this.mapTrack.routeLayer.getSource().clear();this.map.removeLayer(this.mapTrack.routeLayer);this.mapTrack.featureMove = {};this.mapTrack.geometryMove = {};this.mapTrack.timer = null;this.mapTrack.carPoints = [];this.mapTrack.routeIndex = 0;this.mapTrack.routeLayer = {};this.mapTrack.route = null;},},
};
</script><style lang="scss" scoped>
.mapBox {width: 100%;height: 100%;position: relative;
}
.map {width: 100%;height: 100%;
}/deep/.ol-control {display: none;
}/deep/.blueLayer {// filter: grayscale(100%) sepia(21%) invert(100%) saturate(150%) brightness(100%);filter: grayscale(98%) invert(100%) sepia(50%) hue-rotate(180deg) saturate(2000%) brightness(50%) contrast(90%) !important;
}.optionsBox {position: absolute;top: 20px;left: 20px;z-index: 1000;display: flex;align-items: center;
}
</style><!-- 修改提示框样式 -->
<style lang="scss" scoped>
/deep/.ol-tooltip {position: relative;background: rgba(0, 0, 0, 0.5);border-radius: 4px;color: white;padding: 4px 8px;opacity: 0.7;white-space: nowrap;font-size: 12px;cursor: default;user-select: none;
}/deep/ .hidden {display: none;
}/deep/.ol-tooltip-measure {opacity: 1;font-weight: bold;
}/deep/.ol-tooltip-static {background-color: #ffcc33;color: black;border: 1px solid white;
}/deep/.ol-tooltip-measure:before,
/deep/.ol-tooltip-static:before {border-top: 6px solid rgba(0, 0, 0, 0.5);border-right: 6px solid transparent;border-left: 6px solid transparent;content: "";position: absolute;bottom: -6px;margin-left: -7px;left: 50%;
}/deep/.ol-tooltip-static:before {border-top-color: #ffcc33;
}
</style>

更多推荐

openlayers 地图组件封装

本文发布于:2024-03-12 05:05:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1730758.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:组件   地图   openlayers

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!