|
@@ -24,12 +24,14 @@ import GeoJSON from 'ol/format/GeoJSON';
|
|
|
import { fromLonLat } from 'ol/proj';
|
|
|
import axios from 'axios';
|
|
|
import { fromExtent } from 'ol/geom/Polygon';
|
|
|
-import { LinearRing, Polygon } from 'ol/geom';
|
|
|
-import { Tile } from 'ol';
|
|
|
+import { LinearRing, LineString, Polygon } from 'ol/geom';
|
|
|
import {Graticule} from "ol/layer";
|
|
|
-import { mergeGeoJsonPolygons } from '@/utils/gisUtils';
|
|
|
-// import olPlot from 'ol-plot';
|
|
|
-// import { activate } from '../ol-plot/ol-plot'
|
|
|
+import { getPointsCenter, mergeGeoJsonPolygons } from '@/utils/gisUtils';
|
|
|
+import { Cluster } from 'ol/source';
|
|
|
+import CircleStyle from 'ol/style/Circle';
|
|
|
+import Overlay from 'ol/Overlay';
|
|
|
+import { Select } from 'ol/interaction';
|
|
|
+import { click } from 'ol/events/condition';
|
|
|
|
|
|
const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
|
|
|
// proj4.defs('EPSG:4490', '+proj=longlat +ellps=GRS80 +no_defs +type=crs');
|
|
@@ -63,14 +65,14 @@ export class olMap {
|
|
|
fillOpacity: 0,
|
|
|
strokeStyle: 'solid'
|
|
|
};
|
|
|
- // private { currentState, commit, undo, history, future } = useHistory();
|
|
|
- private overlays = [];
|
|
|
- private overlaysData = [];
|
|
|
- private graphicsType = '';
|
|
|
private plot;
|
|
|
private vectorLayer;
|
|
|
+ // 边界遮罩图层
|
|
|
private maskLayer;
|
|
|
- private maskLayer2 = [];
|
|
|
+ private maskLayer2;
|
|
|
+ // 显示信息框
|
|
|
+ private infoWindow;
|
|
|
+ private select;
|
|
|
|
|
|
constructor(options) {
|
|
|
this.options = options;
|
|
@@ -97,6 +99,71 @@ export class olMap {
|
|
|
this.initMouseTool(options.drawTool);
|
|
|
}
|
|
|
this.initLayer(options);
|
|
|
+ // 给标注点添加手势
|
|
|
+ this.map.on('pointermove', (e) => {
|
|
|
+ this.map.getTargetElement().style.cursor = 'auto';
|
|
|
+ const features = this.map.getFeaturesAtPixel(e.pixel);
|
|
|
+ features.forEach((feature) => {
|
|
|
+ const originalFeature = feature.get('features') ? feature.get('features')[0] : '';
|
|
|
+ if (!!originalFeature && originalFeature.get('pointer')) {
|
|
|
+ this.map.getTargetElement().style.cursor = 'pointer'; //设置鼠标样式
|
|
|
+ } else {
|
|
|
+ this.map.getTargetElement().style.cursor = 'auto';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 创建选择交互
|
|
|
+ this.select = new Select({
|
|
|
+ condition: click,
|
|
|
+ filter: (feature, layer) => {
|
|
|
+ // 只有vectorLayer图层可选择
|
|
|
+ return layer === this.vectorLayer;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.map.addInteraction(this.select);
|
|
|
+ // 监听Select交互的select事件
|
|
|
+ this.select.on('select', (event) => {
|
|
|
+ const selectedFeatures = event.selected[0]; // 获取被选中的要素集合
|
|
|
+ const features = selectedFeatures.get('features');
|
|
|
+ if (selectedFeatures && !!features) {
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
+ // 聚合要素
|
|
|
+ const currentZoom = this.map.getView().getZoom();
|
|
|
+ this.map.getView().setZoom(currentZoom + 1);
|
|
|
+ const points = [];
|
|
|
+ features.forEach((feature) => {
|
|
|
+ const geometry = feature.getGeometry(); // 获取要素的几何对象
|
|
|
+ const type = geometry.getType(); // 获取几何类型
|
|
|
+ if (type === 'Point') {
|
|
|
+ points.push(geometry.getCoordinates());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ const newFeature = getPointsCenter(points);
|
|
|
+ this.map.getView().setCenter(newFeature.geometry.coordinates);
|
|
|
+ event.selected = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
async initLayer(options) {
|
|
|
// 添加新的图层
|
|
@@ -254,15 +321,62 @@ export class olMap {
|
|
|
loadendFunc();
|
|
|
}
|
|
|
}
|
|
|
+ // 集群点样式
|
|
|
+ clusterStyle(feature) {
|
|
|
+ const originalFeature = feature.get('features')[0];
|
|
|
+ const size = feature.get('features').length;
|
|
|
+ if (size > 1) {
|
|
|
+ const outerCircle = new CircleStyle({
|
|
|
+ radius: 20,
|
|
|
+ fill: new Fill({
|
|
|
+ color: 'rgba(79, 176, 206, 0.5)'
|
|
|
+ }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: 'rgba(79, 176, 206, 1)'
|
|
|
+ })
|
|
|
+ });
|
|
|
+ return [
|
|
|
+ new Style({
|
|
|
+ image: outerCircle,
|
|
|
+ text: new Text({
|
|
|
+ text: size.toString(),
|
|
|
+ font: '14px sans-serif',
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#ffff'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
+ ];
|
|
|
+ }
|
|
|
|
|
|
+ return new Style({
|
|
|
+ geometry: originalFeature.getGeometry(),
|
|
|
+ image: new Icon({
|
|
|
+ anchor: [0.5, 0.5],
|
|
|
+ scale: 0.146,
|
|
|
+ anchorXUnits: 'fraction',
|
|
|
+ anchorYUnits: 'pixels',
|
|
|
+ src: originalFeature.get('icon')
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
addMarker(points) {
|
|
|
- this.clearMarker('point');
|
|
|
+ this.clearMarker();
|
|
|
+ const features = [];
|
|
|
points.forEach((point) => {
|
|
|
// 创建标注点
|
|
|
const feature = new Feature({
|
|
|
- geometry: new Point(point.lnglat),
|
|
|
- name: point.name
|
|
|
+ // 必须是数字类型,字符串不识别
|
|
|
+ geometry: new Point([Number(point.longitude), Number(point.latitude)]),
|
|
|
+ name: point.name,
|
|
|
+ icon: point.icon,
|
|
|
+ imageHover: point.imageHover,
|
|
|
+ size: point.size,
|
|
|
+ pointer: true,
|
|
|
+ extData: point
|
|
|
});
|
|
|
+ // 设置自定义属性
|
|
|
+ feature.set('pointer', true);
|
|
|
// 定义样式
|
|
|
const style = new Style({
|
|
|
image: new Icon({
|
|
@@ -283,19 +397,46 @@ export class olMap {
|
|
|
})
|
|
|
})
|
|
|
});
|
|
|
-
|
|
|
feature.setStyle(style);
|
|
|
+ features.push(feature);
|
|
|
this.markers.push(point);
|
|
|
- this.vectorLayer.getSource().addFeature(feature);
|
|
|
});
|
|
|
+ const vectorSource = new VectorSource({
|
|
|
+ features: features
|
|
|
+ });
|
|
|
+ const clusterSource = new Cluster({
|
|
|
+ distance: 30,
|
|
|
+ source: vectorSource
|
|
|
+ });
|
|
|
+ this.vectorLayer.setStyle(this.clusterStyle);
|
|
|
+ this.vectorLayer.setSource(clusterSource);
|
|
|
}
|
|
|
-
|
|
|
// 清除所有标加
|
|
|
- clearMarker(id) {
|
|
|
+ clearMarker() {
|
|
|
if (!this.vectorLayer) return;
|
|
|
this.vectorLayer.getSource().clear();
|
|
|
}
|
|
|
|
|
|
+ showInfo(content, position, isCustom) {
|
|
|
+ this.hideInfo();
|
|
|
+ if (!this.infoWindow) {
|
|
|
+ this.infoWindow = new Overlay({
|
|
|
+ element: content,
|
|
|
+ positioning: 'bottom-center', // 你可以根据需要调整定位方式
|
|
|
+ offset: [0, -10] // 偏移量,用于调整覆盖层相对于要素的位置
|
|
|
+ });
|
|
|
+ }
|
|
|
+ this.infoWindow.setPosition(position);
|
|
|
+ this.map.addOverlay(this.infoWindow);
|
|
|
+ }
|
|
|
+
|
|
|
+ hideInfo(flag) {
|
|
|
+ this.map.removeOverlay(this.infoWindow);
|
|
|
+ this.infoWindow = null;
|
|
|
+ if (!!flag && this.select) {
|
|
|
+ this.select.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
/**
|
|
|
*
|
|
|
* @param {Geojon} chaozhou 根据geojson对象创建Featrue对象
|
|
@@ -334,12 +475,24 @@ export class olMap {
|
|
|
this.maskLayer.getSource().addFeature(convertFt);
|
|
|
}
|
|
|
createVecByJson2(json, options) {
|
|
|
- if (this.maskLayer2 && this.maskLayer2.length > 0) {
|
|
|
- this.maskLayer2.forEach((layer) => {
|
|
|
- this.map.addLayer(layer);
|
|
|
- });
|
|
|
+ if (!!this.maskLayer2) {
|
|
|
+ // this.map.addLayer(this.maskLayer);
|
|
|
+ this.map.addLayer(this.maskLayer2);
|
|
|
} else {
|
|
|
- // const layer = new VectorLayer({
|
|
|
+ this.maskLayer2 = new VectorLayer({
|
|
|
+ source: new VectorSource(),
|
|
|
+ style: new Style({
|
|
|
+ fill: new Fill({
|
|
|
+ color: 'rgba(0, 0, 0, 0)'
|
|
|
+ }),
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: options.strokeColor ? options.strokeColor : '#268ab9',
|
|
|
+ width: options.strokeWeight ? options.strokeWeight : 1
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ this.map.addLayer(this.maskLayer2);
|
|
|
+ // this.maskLayer = new VectorLayer({
|
|
|
// source: new VectorSource(),
|
|
|
// style: new Style({
|
|
|
// fill: new Fill({
|
|
@@ -369,57 +522,21 @@ export class olMap {
|
|
|
// const convertFt = new Feature({
|
|
|
// geometry: polygonRing
|
|
|
// });
|
|
|
- // layer.getSource().addFeature(convertFt);
|
|
|
- // this.maskLayer2.push(layer);
|
|
|
- // this.map.addLayer(layer);
|
|
|
+ // this.maskLayer.getSource().addFeature(convertFt);
|
|
|
+ // this.map.addLayer(this.maskLayer);
|
|
|
// 边界部分
|
|
|
json.features.forEach((feature) => {
|
|
|
if (feature.geometry.type === 'Polygon') {
|
|
|
- const polygonPath = feature.geometry.coordinates[0].map((coord) => {
|
|
|
- return [coord[0], coord[1]];
|
|
|
- });
|
|
|
const feature2 = new Feature({
|
|
|
- geometry: new Polygon([polygonPath])
|
|
|
+ geometry: new LineString(feature.geometry.coordinates[0])
|
|
|
});
|
|
|
- const vector = new VectorLayer({
|
|
|
- source: new VectorSource(),
|
|
|
- style: new Style({
|
|
|
- fill: new Fill({
|
|
|
- color: 'rgba(0, 0, 0, 0)'
|
|
|
- }),
|
|
|
- stroke: new Stroke({
|
|
|
- color: options.strokeColor ? options.strokeColor : '#268ab9',
|
|
|
- width: options.strokeWeight ? options.strokeWeight : 1
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- vector.getSource().addFeature(feature2);
|
|
|
- this.maskLayer2.push(vector);
|
|
|
- this.map.addLayer(vector);
|
|
|
+ this.maskLayer2.getSource().addFeature(feature2);
|
|
|
} else if (feature.geometry.type === 'MultiPolygon') {
|
|
|
feature.geometry.coordinates.forEach((polygonCoords) => {
|
|
|
- const polygonPath = polygonCoords.map((ring) => {
|
|
|
- return ring.map((coord) => {
|
|
|
- return [coord[0], coord[1]];
|
|
|
- });
|
|
|
+ const feature2 = new Feature({
|
|
|
+ geometry: new LineString(polygonCoords[0])
|
|
|
});
|
|
|
- const outerPath = polygonPath;
|
|
|
- const feature2 = new Feature({ geometry: new Polygon(outerPath), });
|
|
|
- const vector = new VectorLayer({
|
|
|
- source: new VectorSource(),
|
|
|
- style: new Style({
|
|
|
- fill: new Fill({
|
|
|
- color: 'rgba(0, 0, 0, 0)'
|
|
|
- }),
|
|
|
- stroke: new Stroke({
|
|
|
- color: options.strokeColor ? options.strokeColor : '#268ab9',
|
|
|
- width: options.strokeWeight ? options.strokeWeight : 1
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- vector.getSource().addFeature(feature2);
|
|
|
- this.maskLayer2.push(vector);
|
|
|
- this.map.addLayer(vector);
|
|
|
+ this.maskLayer2.getSource().addFeature(feature2);
|
|
|
});
|
|
|
}
|
|
|
});
|
|
@@ -493,10 +610,14 @@ export class olMap {
|
|
|
}
|
|
|
}
|
|
|
removeMask3(isHide) {
|
|
|
- if (this.maskLayer2 && this.maskLayer2.length > 0) {
|
|
|
- this.maskLayer2.forEach((layer) => {
|
|
|
- this.map.removeLayer(layer);
|
|
|
- });
|
|
|
+ if (this.maskLayer) {
|
|
|
+ this.map.removeLayer(this.maskLayer);
|
|
|
+ if (!isHide) {
|
|
|
+ this.maskLayer = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (this.maskLayer2) {
|
|
|
+ this.map.removeLayer(this.maskLayer2);
|
|
|
if (!isHide) {
|
|
|
this.maskLayer2 = [];
|
|
|
}
|
|
@@ -554,4 +675,10 @@ export class olMap {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+ getVectorLayer() {
|
|
|
+ return this.vectorLayer;
|
|
|
+ }
|
|
|
+ getMap() {
|
|
|
+ return this.map;
|
|
|
+ }
|
|
|
}
|