|
@@ -30,7 +30,7 @@ import { getPointsCenter, mergeGeoJsonPolygons } from '@/utils/gisUtils';
|
|
|
import { Cluster } from 'ol/source';
|
|
|
import CircleStyle from 'ol/style/Circle';
|
|
|
import Overlay from 'ol/Overlay';
|
|
|
-import { Draw, Select } from 'ol/interaction';
|
|
|
+import { DoubleClickZoom, DragPan, Draw, Select } from 'ol/interaction';
|
|
|
import { click } from 'ol/events/condition';
|
|
|
import Circle from 'ol/geom/Circle';
|
|
|
import { deepClone, getRgba, hexToRgba, initDrag, rgbToRgba } from '@/utils';
|
|
@@ -93,6 +93,7 @@ export class olMap {
|
|
|
private traceFeature;
|
|
|
// 自定义绘制结束调用方法
|
|
|
private drawEndMethod;
|
|
|
+ private selectedFeature;
|
|
|
|
|
|
constructor(options) {
|
|
|
this.options = options;
|
|
@@ -136,6 +137,7 @@ export class olMap {
|
|
|
// 创建选择交互
|
|
|
this.select = new Select({
|
|
|
condition: click,
|
|
|
+ style: null,
|
|
|
filter: (feature, layer) => {
|
|
|
// 只有vectorLayer图层可选择
|
|
|
return layer === this.vectorLayer;
|
|
@@ -150,20 +152,16 @@ export class olMap {
|
|
|
const originalFeature = features[0];
|
|
|
const size = features.length;
|
|
|
if (size === 1) {
|
|
|
- // 设置新的样式(更换图标)
|
|
|
- selectedFeatures.setStyle(
|
|
|
- new Style({
|
|
|
- image: new Icon({
|
|
|
- anchor: [0.5, 0.5],
|
|
|
- scale: 0.146,
|
|
|
- anchorXUnits: 'fraction',
|
|
|
- anchorYUnits: 'pixels',
|
|
|
- src: originalFeature.get('imageHover')
|
|
|
- })
|
|
|
- })
|
|
|
- );
|
|
|
- const extData = originalFeature.get('extData');
|
|
|
- options.onMarkerClick(extData);
|
|
|
+ if (this.selectedFeature !== originalFeature) {
|
|
|
+ if (this.selectedFeature) {
|
|
|
+ this.selectedFeature.set('icon', this.selectedFeature.get('image'));
|
|
|
+ }
|
|
|
+ this.selectedFeature = originalFeature;
|
|
|
+ const icon = originalFeature.get('imageHover');
|
|
|
+ const extData = originalFeature.get('extData');
|
|
|
+ originalFeature.set('icon', icon);
|
|
|
+ options.onMarkerClick(extData);
|
|
|
+ }
|
|
|
} else {
|
|
|
// 聚合要素
|
|
|
this.select.getFeatures().clear();
|
|
@@ -311,7 +309,6 @@ export class olMap {
|
|
|
// 继续编辑编辑
|
|
|
this.drawGraphics(this.drawOptions.graphicsType);
|
|
|
}
|
|
|
-
|
|
|
// 绘制图形
|
|
|
drawGraphics(newOptions: MouseTool) {
|
|
|
const typeList = {
|
|
@@ -321,9 +318,9 @@ export class olMap {
|
|
|
measureArea: 'Polygon',
|
|
|
straightLine: 'LineString',
|
|
|
marker: 'Point',
|
|
|
- text: 'Point'
|
|
|
+ text: 'Point',
|
|
|
+ anyLine: 'AnyLine'
|
|
|
};
|
|
|
- debugger
|
|
|
const data = getRgba(newOptions.color);
|
|
|
let geometryFunction = null;
|
|
|
if (newOptions.graphicsType === 'rectangle') {
|
|
@@ -359,52 +356,56 @@ export class olMap {
|
|
|
this.drawOptions.size = newOptions.size;
|
|
|
}
|
|
|
this.closeDraw();
|
|
|
- // 创建绘制交互
|
|
|
- let style = new Style({
|
|
|
- stroke: new Stroke({
|
|
|
- color: rgbToRgba(this.drawOptions.strokeColor, this.drawOptions.strokeOpacity),
|
|
|
- width: this.drawOptions.strokeWeight
|
|
|
- }),
|
|
|
- fill: new Fill({
|
|
|
- color: rgbToRgba(this.drawOptions.fillColor, this.drawOptions.fillOpacity)
|
|
|
- })
|
|
|
- });
|
|
|
- this.drawTool = new Draw({
|
|
|
- source: this.drawVector.getSource(),
|
|
|
- type: typeList[newOptions.graphicsType],
|
|
|
- geometryFunction: geometryFunction,
|
|
|
- style: style
|
|
|
- });
|
|
|
- // 添加绘制交互到地图
|
|
|
- this.map.addInteraction(this.drawTool);
|
|
|
- // 监听绘制结束事件
|
|
|
- this.drawTool.on('drawend', (event) => {
|
|
|
- const feature = event.feature;
|
|
|
- // 获取几何对象
|
|
|
- if (newOptions.graphicsType !== 'marker') {
|
|
|
- if (newOptions.graphicsType === 'measureArea') {
|
|
|
- const geometry = feature.getGeometry();
|
|
|
- const coordinates = geometry.getCoordinates();
|
|
|
- const pathArr = coordinates[0];
|
|
|
- const area = turf.area(turf.polygon([pathArr]));
|
|
|
- style = new Style({
|
|
|
- stroke: style.getStroke(),
|
|
|
- fill: style.getFill(),
|
|
|
- text: new Text({
|
|
|
- text: '区域面积' + area.toFixed(2) + '平方米',
|
|
|
- font: '14px Calibri,sans-serif',
|
|
|
- fill: new Fill({ color: '#000' }),
|
|
|
- stroke: new Stroke({
|
|
|
- color: '#fff',
|
|
|
- width: 3
|
|
|
- }),
|
|
|
- overflow: true
|
|
|
- })
|
|
|
- });
|
|
|
+ if (newOptions.graphicsType === 'anyLine') {
|
|
|
+ this.drawAnyLine();
|
|
|
+ } else {
|
|
|
+ // 创建绘制交互
|
|
|
+ let style = new Style({
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: rgbToRgba(this.drawOptions.strokeColor, this.drawOptions.strokeOpacity),
|
|
|
+ width: this.drawOptions.strokeWeight
|
|
|
+ }),
|
|
|
+ fill: new Fill({
|
|
|
+ color: rgbToRgba(this.drawOptions.fillColor, this.drawOptions.fillOpacity)
|
|
|
+ })
|
|
|
+ });
|
|
|
+ this.drawTool = new Draw({
|
|
|
+ source: this.drawVector.getSource(),
|
|
|
+ type: typeList[newOptions.graphicsType],
|
|
|
+ geometryFunction: geometryFunction,
|
|
|
+ style: style
|
|
|
+ });
|
|
|
+ // 添加绘制交互到地图
|
|
|
+ this.map.addInteraction(this.drawTool);
|
|
|
+ // 监听绘制结束事件
|
|
|
+ this.drawTool.on('drawend', (event) => {
|
|
|
+ const feature = event.feature;
|
|
|
+ // 获取几何对象
|
|
|
+ if (newOptions.graphicsType !== 'marker') {
|
|
|
+ if (newOptions.graphicsType === 'measureArea') {
|
|
|
+ const geometry = feature.getGeometry();
|
|
|
+ const coordinates = geometry.getCoordinates();
|
|
|
+ const pathArr = coordinates[0];
|
|
|
+ const area = turf.area(turf.polygon([pathArr]));
|
|
|
+ style = new Style({
|
|
|
+ stroke: style.getStroke(),
|
|
|
+ fill: style.getFill(),
|
|
|
+ text: new Text({
|
|
|
+ text: '区域面积' + area.toFixed(2) + '平方米',
|
|
|
+ font: '14px Calibri,sans-serif',
|
|
|
+ fill: new Fill({ color: '#000' }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff',
|
|
|
+ width: 3
|
|
|
+ }),
|
|
|
+ overflow: true
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
+ feature.setStyle(style);
|
|
|
}
|
|
|
- feature.setStyle(style);
|
|
|
- }
|
|
|
- });
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
return this.drawOptions;
|
|
@@ -484,6 +485,74 @@ export class olMap {
|
|
|
data.id = id;
|
|
|
return { text, data };
|
|
|
}
|
|
|
+ drawAnyLine() {
|
|
|
+ document.addEventListener('touchend', this.handleTouchEnd);
|
|
|
+ this.map.on('pointerdown', this.handleTouchStart);
|
|
|
+ this.map.on('pointermove', this.handleTouchMove.bind(null, this.options));
|
|
|
+ document.addEventListener('mouseup', this.handleTouchEnd.bind(null, this.options));
|
|
|
+ }
|
|
|
+ handleTouchStart(e) {
|
|
|
+ this.drawing = true;
|
|
|
+ const interactions = this.map.getInteractions();
|
|
|
+ interactions.forEach((interaction) => {
|
|
|
+ if (interaction instanceof DragPan || interaction instanceof DoubleClickZoom) {
|
|
|
+ interaction.setActive(false); // 修改为需要的值,true或false
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.path = [e.lnglat];
|
|
|
+ // if (this.anyLine) {
|
|
|
+ // map.remove(anyLine);
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ handleTouchMove(options, e) {
|
|
|
+ if (!this.drawing) return;
|
|
|
+ this.path.push(e.lnglat);
|
|
|
+ // if (anyLine) {
|
|
|
+ // map.remove(anyLine);
|
|
|
+ // }
|
|
|
+ this.anyLine = new Feature({
|
|
|
+ geometry: new LineString(this.path) // path为坐标数组,如[[x1,y1], [x2,y2]]
|
|
|
+ });
|
|
|
+ const lineStyle = new Style({
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: hexToRgba(options.strokeColor, options.strokeOpacity), // 合并颜色与透明度
|
|
|
+ width: options.strokeWeight,
|
|
|
+ lineJoin: 'round' // 线段连接处圆角
|
|
|
+ })
|
|
|
+ });
|
|
|
+ this.anyLine.setStyle(lineStyle);
|
|
|
+ // new AMap.Polyline({
|
|
|
+ // path: path,
|
|
|
+ // strokeColor: options.strokeColor,
|
|
|
+ // strokeOpacity: options.strokeOpacity,
|
|
|
+ // strokeWeight: options.strokeWeight,
|
|
|
+ // strokeStyle: options.strokeStyle,
|
|
|
+ // lineJoin: 'round'
|
|
|
+ // });
|
|
|
+ this.drawVector.getSource().addFeature(this.anyLine);
|
|
|
+ }
|
|
|
+ handleTouchEnd(options) {
|
|
|
+ // drawing = false;
|
|
|
+ // map.setStatus({
|
|
|
+ // showIndoorMap: true,
|
|
|
+ // dragEnable: true,
|
|
|
+ // keyboardEnable: true,
|
|
|
+ // doubleClickZoom: true,
|
|
|
+ // zoomEnable: true,
|
|
|
+ // rotateEnable: true
|
|
|
+ // });
|
|
|
+ // map.off('touchstart', handleTouchStart);
|
|
|
+ // map.on('touchmove', handleTouchMove.bind(null, options));
|
|
|
+ // document.addEventListener('touchend', handleTouchEnd.bind(null, options));
|
|
|
+ // map.off('mousedown', handleTouchStart);
|
|
|
+ // map.off('mousemove', handleTouchMove);
|
|
|
+ // document.removeEventListener('mouseup', handleTouchEnd);
|
|
|
+ // if (!!drawEndMethod) {
|
|
|
+ // drawEndMethod(options, anyLine);
|
|
|
+ // }
|
|
|
+ // anyLine = null;
|
|
|
+ }
|
|
|
// 关闭绘制
|
|
|
closeDraw() {
|
|
|
if (!this.drawTool) return;
|
|
@@ -551,21 +620,46 @@ export class olMap {
|
|
|
})
|
|
|
];
|
|
|
}
|
|
|
-
|
|
|
- return new Style({
|
|
|
+ const pointSize = originalFeature.get('size');
|
|
|
+ const originalWidth = originalFeature.get('originalWidth');
|
|
|
+ const originalHeight = originalFeature.get('originalHeight');
|
|
|
+ const icon = originalFeature.get('icon');
|
|
|
+ const name = originalFeature.get('name');
|
|
|
+ const showName = originalFeature.get('showName');
|
|
|
+ const scale = !!pointSize[0] ? pointSize[0] / originalWidth : 1;
|
|
|
+ const style = new Style({
|
|
|
geometry: originalFeature.getGeometry(),
|
|
|
image: new Icon({
|
|
|
+ src: icon,
|
|
|
+ scale: scale,
|
|
|
anchor: [0.5, 0.5],
|
|
|
- scale: 0.146,
|
|
|
anchorXUnits: 'fraction',
|
|
|
- anchorYUnits: 'pixels',
|
|
|
- src: originalFeature.get('icon')
|
|
|
+ anchorYUnits: 'fraction'
|
|
|
})
|
|
|
});
|
|
|
+ if (!!showName) {
|
|
|
+ style.setText(
|
|
|
+ new Text({
|
|
|
+ text: name,
|
|
|
+ font: '12px sans-serif',
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#000'
|
|
|
+ }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff',
|
|
|
+ width: 3
|
|
|
+ }),
|
|
|
+ offsetY: (originalHeight / 2) * scale + 4
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return style;
|
|
|
}
|
|
|
addMarker(points) {
|
|
|
this.clearMarker();
|
|
|
- const features = [];
|
|
|
+ const vectorSource = new VectorSource({
|
|
|
+ features: []
|
|
|
+ });
|
|
|
points.forEach((point) => {
|
|
|
// 创建标注点
|
|
|
const feature = new Feature({
|
|
@@ -573,47 +667,27 @@ export class olMap {
|
|
|
geometry: new Point([Number(point.longitude), Number(point.latitude)]),
|
|
|
name: point.name,
|
|
|
icon: point.icon,
|
|
|
+ image: point.icon,
|
|
|
imageHover: point.imageHover,
|
|
|
size: point.size,
|
|
|
+ showName: point.showName,
|
|
|
pointer: true,
|
|
|
extData: point
|
|
|
});
|
|
|
// 设置自定义属性
|
|
|
- feature.set('pointer', true);
|
|
|
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
|
|
|
- }),
|
|
|
- text: new Text({
|
|
|
- text: point.name,
|
|
|
- fill: new Fill({
|
|
|
- color: '#000'
|
|
|
- }),
|
|
|
- stroke: new Stroke({
|
|
|
- color: '#fff',
|
|
|
- width: 3
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- features.setStyle(style);
|
|
|
+ const height = img.width;
|
|
|
+ feature.set('originalWidth', width);
|
|
|
+ feature.set('originalHeight', height);
|
|
|
+ feature.set('img', img);
|
|
|
+ vectorSource.addFeature(feature);
|
|
|
};
|
|
|
img.src = point.icon; // 设置图片的 URL,触发加载
|
|
|
- features.push(feature);
|
|
|
this.markers.push(point);
|
|
|
});
|
|
|
- const vectorSource = new VectorSource({
|
|
|
- features: features
|
|
|
- });
|
|
|
const clusterSource = new Cluster({
|
|
|
distance: 30,
|
|
|
source: vectorSource
|
|
@@ -1004,7 +1078,7 @@ export class olMap {
|
|
|
this.traceFeature = new Feature({
|
|
|
geometry: new LineString(lineArr)
|
|
|
});
|
|
|
- let route = new LineString(lineArr);
|
|
|
+ const route = new LineString(lineArr);
|
|
|
this.carLayer = new VectorLayer({
|
|
|
source: source,
|
|
|
style: new Style({
|