|
@@ -33,10 +33,11 @@ import Overlay from 'ol/Overlay';
|
|
|
import { Draw, Select } from 'ol/interaction';
|
|
|
import { click } from 'ol/events/condition';
|
|
|
import Circle from 'ol/geom/Circle';
|
|
|
-import { deepClone, hexToRgba } from '@/utils';
|
|
|
+import { deepClone, getRgba, hexToRgba, initDrag, rgbToRgba } from '@/utils';
|
|
|
import { createBox } from 'ol/interaction/Draw';
|
|
|
import * as turf from '@turf/turf';
|
|
|
import { nanoid } from 'nanoid';
|
|
|
+import carImg from '@/assets/images/car.png';
|
|
|
|
|
|
const tk = 'a8df87f1695d224d2679aa805c1268d9';
|
|
|
const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
|
|
@@ -86,6 +87,10 @@ export class olMap {
|
|
|
// 显示信息框
|
|
|
private infoWindow;
|
|
|
private select;
|
|
|
+ // 车辆轨迹
|
|
|
+ private carLayer;
|
|
|
+ private carFeature;
|
|
|
+ private traceFeature;
|
|
|
|
|
|
constructor(options) {
|
|
|
this.options = options;
|
|
@@ -316,6 +321,7 @@ export class olMap {
|
|
|
marker: 'Point',
|
|
|
text: 'Point'
|
|
|
};
|
|
|
+ const data = getRgba(newOptions.color);
|
|
|
let geometryFunction = null;
|
|
|
if (newOptions.graphicsType === 'rectangle') {
|
|
|
// 绘制矩形的方法
|
|
@@ -336,11 +342,12 @@ export class olMap {
|
|
|
} else {
|
|
|
this.drawOptions = {
|
|
|
type: newOptions.graphicsType,
|
|
|
- strokeColor: newOptions.color,
|
|
|
+ title: newOptions.title,
|
|
|
+ strokeColor: !!data.color ? data.color : newOptions.color,
|
|
|
strokeOpacity: 1,
|
|
|
strokeWeight: 1,
|
|
|
- fillColor: newOptions.color,
|
|
|
- fillOpacity: newOptions.drawType === '1' ? '0' : '0.5',
|
|
|
+ fillColor: data.color,
|
|
|
+ fillOpacity: data.opacity,
|
|
|
strokeStyle: 'solid'
|
|
|
};
|
|
|
if (newOptions.graphicsType === 'marker') {
|
|
@@ -352,11 +359,11 @@ export class olMap {
|
|
|
// 创建绘制交互
|
|
|
let style = new Style({
|
|
|
stroke: new Stroke({
|
|
|
- color: hexToRgba(this.drawOptions.strokeColor, this.drawOptions.strokeOpacity),
|
|
|
+ color: rgbToRgba(this.drawOptions.strokeColor, this.drawOptions.strokeOpacity),
|
|
|
width: this.drawOptions.strokeWeight
|
|
|
}),
|
|
|
fill: new Fill({
|
|
|
- color: hexToRgba(this.drawOptions.fillColor, this.drawOptions.fillOpacity)
|
|
|
+ color: rgbToRgba(this.drawOptions.fillColor, this.drawOptions.fillOpacity)
|
|
|
})
|
|
|
});
|
|
|
this.drawTool = new Draw({
|
|
@@ -570,27 +577,34 @@ export class olMap {
|
|
|
});
|
|
|
// 设置自定义属性
|
|
|
feature.set('pointer', true);
|
|
|
- // 定义样式
|
|
|
- const style = new Style({
|
|
|
- image: new Icon({
|
|
|
- anchor: [0.5, 0.5],
|
|
|
- scale: 0.146,
|
|
|
- anchorXUnits: 'fraction',
|
|
|
- anchorYUnits: 'pixels',
|
|
|
- src: point.icon
|
|
|
- }),
|
|
|
- text: new Text({
|
|
|
- text: point.name,
|
|
|
- fill: new Fill({
|
|
|
- color: '#000'
|
|
|
+ const img = new Image();
|
|
|
+ img.onload = () => {
|
|
|
+ // 图片加载完成后,可以访问其 width 和 height 属性
|
|
|
+ const width = img.width;
|
|
|
+ const height = img.height;
|
|
|
+ const style = new Style({
|
|
|
+ image: new Icon({
|
|
|
+ anchor: [0.5, 0.5],
|
|
|
+ anchorXUnits: 'fraction',
|
|
|
+ anchorYUnits: 'pixels',
|
|
|
+ src: point.icon,
|
|
|
+ size: [width, height],
|
|
|
+ scale: !!point.size[0] ? point.size[0] / width : 1
|
|
|
}),
|
|
|
- stroke: new Stroke({
|
|
|
- color: '#fff',
|
|
|
- width: 3
|
|
|
+ text: new Text({
|
|
|
+ text: point.name,
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#000'
|
|
|
+ }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff',
|
|
|
+ width: 3
|
|
|
+ })
|
|
|
})
|
|
|
- })
|
|
|
- });
|
|
|
- feature.setStyle(style);
|
|
|
+ });
|
|
|
+ features.setStyle(style);
|
|
|
+ };
|
|
|
+ img.src = point.icon; // 设置图片的 URL,触发加载
|
|
|
features.push(feature);
|
|
|
this.markers.push(point);
|
|
|
});
|
|
@@ -620,6 +634,7 @@ export class olMap {
|
|
|
});
|
|
|
}
|
|
|
this.infoWindow.setPosition(position);
|
|
|
+ initDrag(this.infoWindow.element);
|
|
|
this.map.addOverlay(this.infoWindow);
|
|
|
}
|
|
|
|
|
@@ -898,11 +913,11 @@ export class olMap {
|
|
|
feature.setStyle(
|
|
|
new Style({
|
|
|
stroke: new Stroke({
|
|
|
- color: hexToRgba(data.strokeColor, data.strokeOpacity),
|
|
|
+ color: rgbToRgba(data.strokeColor, data.strokeOpacity),
|
|
|
width: data.strokeWeight
|
|
|
}),
|
|
|
fill: new Fill({
|
|
|
- color: hexToRgba(data.fillColor, data.fillOpacity)
|
|
|
+ color: rgbToRgba(data.fillColor, data.fillOpacity)
|
|
|
})
|
|
|
})
|
|
|
);
|
|
@@ -915,17 +930,213 @@ export class olMap {
|
|
|
feature.setStyle(
|
|
|
new Style({
|
|
|
stroke: new Stroke({
|
|
|
- color: hexToRgba(data.strokeColor, data.strokeOpacity),
|
|
|
+ color: rgbToRgba(data.strokeColor, data.strokeOpacity),
|
|
|
+ width: data.strokeWeight
|
|
|
+ }),
|
|
|
+ fill: new Fill({
|
|
|
+ color: rgbToRgba(data.fillColor, data.fillOpacity)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ );
|
|
|
+ this.drawVector.getSource().addFeature(feature);
|
|
|
+ return feature;
|
|
|
+ }
|
|
|
+ createLineString(data) {
|
|
|
+ const lineString = new LineString(data.path);
|
|
|
+ const feature = new Feature(lineString);
|
|
|
+ feature.setStyle(
|
|
|
+ new Style({
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: rgbToRgba(data.strokeColor, data.strokeOpacity),
|
|
|
width: data.strokeWeight
|
|
|
}),
|
|
|
fill: new Fill({
|
|
|
- color: hexToRgba(data.fillColor, data.fillOpacity)
|
|
|
+ color: rgbToRgba(data.fillColor, data.fillOpacity)
|
|
|
})
|
|
|
})
|
|
|
);
|
|
|
this.drawVector.getSource().addFeature(feature);
|
|
|
return feature;
|
|
|
}
|
|
|
+ trackPlayback(lineArr) {
|
|
|
+ if (!!this.carFeature) {
|
|
|
+ this.carLayer.getSource().removeFeature(this.carFeature);
|
|
|
+ }
|
|
|
+ if (!!this.traceFeature) {
|
|
|
+ this.carLayer.getSource().removeFeature(this.traceFeature);
|
|
|
+ }
|
|
|
+ const getAngle = (point1, point2) => {
|
|
|
+ let arc = 0;
|
|
|
+ if (point2 && point2.length && point1 && point1.length) {
|
|
|
+ if ((point2[0] - point1[0] >= 0 && point2[1] - point1[1] >= 0) || (point2[0] - point1[0] < 0 && point2[1] - point1[1] > 0)) {
|
|
|
+ arc = Math.atan((point2[0] - point1[0]) / (point2[1] - point1[1]));
|
|
|
+ } else if ((point2[0] - point1[0] > 0 && point2[1] - point1[1] < 0) || (point2[0] - point1[0] < 0 && point2[1] - point1[1] < 0)) {
|
|
|
+ arc = Math.PI + Math.atan((point2[0] - point1[0]) / (point2[1] - point1[1]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return arc;
|
|
|
+ };
|
|
|
+ let lastTime = Date.now();
|
|
|
+ const source = new VectorSource();
|
|
|
+ let distance = 0;
|
|
|
+ const angle = getAngle(lineArr[0], lineArr[1]);
|
|
|
+ const speed = 500;
|
|
|
+ let animationFlag = false;
|
|
|
+ this.carFeature = new Feature({
|
|
|
+ geometry: new Point(lineArr[0])
|
|
|
+ });
|
|
|
+ const icon = new Icon({
|
|
|
+ crossOrigin: 'anonymous',
|
|
|
+ src: carImg,
|
|
|
+ width: 26,
|
|
|
+ height: 52,
|
|
|
+ rotation: angle
|
|
|
+ });
|
|
|
+ this.carFeature.setStyle(
|
|
|
+ new Style({
|
|
|
+ image: icon
|
|
|
+ })
|
|
|
+ );
|
|
|
+ this.traceFeature = new Feature({
|
|
|
+ geometry: new LineString(lineArr)
|
|
|
+ });
|
|
|
+ let route = new LineString(lineArr);
|
|
|
+ this.carLayer = new VectorLayer({
|
|
|
+ source: source,
|
|
|
+ style: new Style({
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: 'rgb(37,232,142)',
|
|
|
+ width: 5
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ this.carLayer.getSource().addFeatures([this.carFeature, this.traceFeature]);
|
|
|
+ const move = (e) => {
|
|
|
+ const time = e.frameState.time;
|
|
|
+ // 时间戳差(毫秒)
|
|
|
+ const elapsedTime = time - lastTime;
|
|
|
+ // 距离(其实是比例的概念)
|
|
|
+ distance = distance + (speed * elapsedTime) / 1e6;
|
|
|
+ if (distance >= 1) {
|
|
|
+ distance = 0;
|
|
|
+ animationFlag = false;
|
|
|
+ stopAnimation();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 保存当前时间
|
|
|
+ lastTime = time;
|
|
|
+ // 上次坐标
|
|
|
+ const lastCoord = this.carFeature.getGeometry().getCoordinates();
|
|
|
+ // 获取新位置的坐标点
|
|
|
+ const curCoord = route.getCoordinateAt(distance);
|
|
|
+ // 设置新坐标
|
|
|
+ this.carFeature.getGeometry().setCoordinates(curCoord);
|
|
|
+ this.map.getView().setCenter(curCoord);
|
|
|
+ // 设置角度
|
|
|
+ this.carFeature.getStyle().getImage().setRotation(getAngle(lastCoord, curCoord));
|
|
|
+ // 调用地图渲染
|
|
|
+ this.map.render();
|
|
|
+ };
|
|
|
+
|
|
|
+ const stopAnimation = () => {
|
|
|
+ this.carLayer.un('postrender', move);
|
|
|
+ };
|
|
|
+ this.map.addLayer(this.carLayer);
|
|
|
+ this.carLayer.on('postrender', move);
|
|
|
+ // 触发地图渲染
|
|
|
+ const geo = this.carFeature.getGeometry().clone();
|
|
|
+ this.carFeature.setGeometry(geo);
|
|
|
+ }
|
|
|
+ drawData(data) {
|
|
|
+ const res = [];
|
|
|
+ data.forEach((item) => {
|
|
|
+ let graphic;
|
|
|
+ if (['rectangle', 'polygon', 'anyLine'].includes(item.type)) {
|
|
|
+ graphic = this.createPolygon(item);
|
|
|
+ graphic.set('id', item.id);
|
|
|
+ res.push(graphic);
|
|
|
+ } else if (item.type === 'circle') {
|
|
|
+ graphic = this.createCircle(item);
|
|
|
+ graphic.set('id', item.id);
|
|
|
+ res.push(graphic);
|
|
|
+ } else if (item.type === 'straightLine') {
|
|
|
+ graphic = this.createLineString(item);
|
|
|
+ graphic.set('id', item.id);
|
|
|
+ res.push(graphic);
|
|
|
+ } else if (item.type === 'text') {
|
|
|
+ const { text } = this.addText(item);
|
|
|
+ res.push(text);
|
|
|
+ } else if (item.type === 'measureArea') {
|
|
|
+ graphic = this.createPolygon(item);
|
|
|
+ graphic.set('id', item.id);
|
|
|
+ const style = new Style({
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: rgbToRgba(item.strokeColor, item.strokeOpacity),
|
|
|
+ width: item.strokeWeight
|
|
|
+ }),
|
|
|
+ fill: new Fill({
|
|
|
+ color: rgbToRgba(item.fillColor, item.fillOpacity)
|
|
|
+ }),
|
|
|
+ text: new Text({
|
|
|
+ text: '区域面积' + item.area.toFixed(2) + '平方米',
|
|
|
+ font: '14px Calibri,sans-serif',
|
|
|
+ fill: new Fill({ color: '#000' }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff',
|
|
|
+ width: 3
|
|
|
+ }),
|
|
|
+ overflow: true
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ graphic.setStyle(style);
|
|
|
+ res.push(graphic);
|
|
|
+ } else if (item.type === 'marker') {
|
|
|
+ // 创建标注点
|
|
|
+ const marker = new Feature({
|
|
|
+ // 必须是数字类型,字符串不识别
|
|
|
+ geometry: new Point([item.longitude, item.latitude]),
|
|
|
+ // name: item.name,
|
|
|
+ // icon: item.icon,
|
|
|
+ // imageHover: item.imageHover,
|
|
|
+ // size: item.size,
|
|
|
+ pointer: true
|
|
|
+ });
|
|
|
+ marker.set('id', item.id);
|
|
|
+ const img = new Image();
|
|
|
+ img.onload = () => {
|
|
|
+ // 图片加载完成后,可以访问其 width 和 height 属性
|
|
|
+ const width = img.width;
|
|
|
+ const height = img.height;
|
|
|
+ const style = new Style({
|
|
|
+ image: new Icon({
|
|
|
+ anchor: [0.5, 0.5],
|
|
|
+ anchorXUnits: 'fraction',
|
|
|
+ anchorYUnits: 'pixels',
|
|
|
+ src: item.icon,
|
|
|
+ size: [width, height],
|
|
|
+ scale: !!item.size[0] ? item.size[0] / width : 1
|
|
|
+ }),
|
|
|
+ text: new Text({
|
|
|
+ text: item.name,
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#000'
|
|
|
+ }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff',
|
|
|
+ width: 3
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ marker.setStyle(style);
|
|
|
+ };
|
|
|
+ img.src = item.icon; // 设置图片的 URL,触发加载
|
|
|
+ this.drawVector.getSource().addFeature(marker);
|
|
|
+ res.push(marker);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return res;
|
|
|
+ }
|
|
|
getVectorLayer() {
|
|
|
return this.vectorLayer;
|
|
|
}
|