|
@@ -6,21 +6,22 @@
|
|
|
import { Map, View } from 'ol'
|
|
|
import SourceVector from 'ol/source/Vector'
|
|
|
import LayerVector from 'ol/layer/Vector'
|
|
|
- import Vector from 'ol/source/Vector.js'
|
|
|
+ import Cluster from 'ol/source/Cluster.js'
|
|
|
+ import { defaults } from 'ol/interaction'
|
|
|
// import OSM from "ol/source/OSM";
|
|
|
import { Circle, Fill, Stroke, Style, Text, Icon } from 'ol/style'
|
|
|
import { Zoom } from 'ol/control'
|
|
|
import { fromLonLat } from 'ol/proj'
|
|
|
+ import { boundingExtent } from 'ol/extent.js'
|
|
|
import Feature from 'ol/Feature'
|
|
|
import Point from 'ol/geom/Point'
|
|
|
import GeoJSON from 'ol/format/GeoJSON'
|
|
|
import videoIcon from '@/assets/images/video-icon.png'
|
|
|
- import { router } from '@/router'
|
|
|
import { useOutsideHomeStore } from '@/stores/modules/home'
|
|
|
|
|
|
const useHomeStore = useOutsideHomeStore()
|
|
|
|
|
|
- const map = ref(null)
|
|
|
+ const map = shallowRef(null)
|
|
|
|
|
|
const labelStyle = new Style({
|
|
|
text: new Text({
|
|
@@ -37,6 +38,18 @@
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
+ // 基础样式
|
|
|
+ const basePointStyle = new Style({
|
|
|
+ image: new Icon({
|
|
|
+ src: videoIcon,
|
|
|
+ scale: 1,
|
|
|
+ anchor: [0.5, 0.5],
|
|
|
+ rotateWithView: true,
|
|
|
+ rotation: 0,
|
|
|
+ opacity: 1
|
|
|
+ }),
|
|
|
+ count: 1
|
|
|
+ })
|
|
|
// GeoJson图层列表
|
|
|
const vectorsJson = [
|
|
|
// 国界线
|
|
@@ -150,7 +163,7 @@
|
|
|
console.log(result)
|
|
|
} else {
|
|
|
result.push(
|
|
|
- new Vector({
|
|
|
+ new SourceVector({
|
|
|
url: `/background/geojson/${file}.json`, // 第一个 GeoJSON 文件的路径
|
|
|
format: new GeoJSON()
|
|
|
})
|
|
@@ -186,6 +199,103 @@
|
|
|
return layers
|
|
|
}
|
|
|
|
|
|
+ // 根据范围随机生成经纬度点位 rangeArr = [minLat, maxLat, minLon, maxLon]
|
|
|
+ const createPointsByRange = (num, rangeArr = [39.9037, 40.9892, 115.2, 117.4]) => {
|
|
|
+ const [minLat, maxLat, minLon, maxLon] = rangeArr
|
|
|
+ const points = []
|
|
|
+ for (var i = 0; i < num; i++) {
|
|
|
+ var lat = Math.random() * (maxLat - minLat) + minLat
|
|
|
+ var lon = Math.random() * (maxLon - minLon) + minLon
|
|
|
+ points.push([lon, lat])
|
|
|
+ }
|
|
|
+ return points
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentDis = ref(150)
|
|
|
+ // 根据数据创建聚合图层
|
|
|
+ const createCluster = (points, zindex) => {
|
|
|
+ const features = points.map((e) => {
|
|
|
+ // ol.proj.fromLonLat用于将经纬度坐标从 WGS84 坐标系转换为地图投影坐标系
|
|
|
+ const feature = new Feature({
|
|
|
+ geometry: new Point(fromLonLat(e)),
|
|
|
+ custom: {
|
|
|
+ id: Math.ceil(Math.random() * 100000)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return feature
|
|
|
+ })
|
|
|
+ // 根据points创建一个新的数据源和要素数组,
|
|
|
+ const vectorSource = new SourceVector({
|
|
|
+ features
|
|
|
+ })
|
|
|
+
|
|
|
+ // 根据点位创建聚合资源
|
|
|
+ const clusterSource = new Cluster({
|
|
|
+ distance: currentDis.value, // 设置多少像素以内的点位进行聚合
|
|
|
+ source: vectorSource
|
|
|
+ })
|
|
|
+ // 创建带有数据源的矢量图层,将创建的聚合字段作为source
|
|
|
+ const clusters = new LayerVector({
|
|
|
+ source: clusterSource,
|
|
|
+ style: (feature) => {
|
|
|
+ return setFeatureStyle(feature) // 设置聚合点的样式
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 将矢量图层添加到地图上
|
|
|
+ map.value.addLayer(clusters)
|
|
|
+ // sv.setZIndex(zindex) // 设置层级
|
|
|
+ return clusters
|
|
|
+ }
|
|
|
+
|
|
|
+ const countStyles = {}
|
|
|
+ // 生成点位聚合显示的数字样式
|
|
|
+ const createCountPointStyle = (size) => {
|
|
|
+ // 计算一个动态的 radius
|
|
|
+ const radius = 20 + Math.max(0, String(size).length - 2) * 10
|
|
|
+ // const rcolor =
|
|
|
+ // '#' +
|
|
|
+ // parseInt(Math.random() * 0xffffff)
|
|
|
+ // .toString(16)
|
|
|
+ // .padStart(6, '0')
|
|
|
+ return new Style({
|
|
|
+ image: new Circle({
|
|
|
+ radius,
|
|
|
+ stroke: new Stroke({
|
|
|
+ color: '#fff'
|
|
|
+ }),
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#3399CC'
|
|
|
+ })
|
|
|
+ }),
|
|
|
+ text: new Text({
|
|
|
+ text: size.toString(),
|
|
|
+ fill: new Fill({
|
|
|
+ color: '#fff'
|
|
|
+ }),
|
|
|
+ scale: 2,
|
|
|
+ textBaseline: 'middle'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置聚合点的样式
|
|
|
+ const setFeatureStyle = (feature) => {
|
|
|
+ // 获取聚合点小有几个点位
|
|
|
+ const size = feature.get('features').length
|
|
|
+ // 设置聚合点的count参数
|
|
|
+ feature.set('count', size)
|
|
|
+ // 如果是1,直接展示点位的样式
|
|
|
+ if (size === 1) {
|
|
|
+ return basePointStyle
|
|
|
+ } else {
|
|
|
+ // 如果是聚合点,查看countStyles是否存储了这个聚合点的数字样式,如果不存在,生成一个并存储
|
|
|
+ if (!countStyles[size]) {
|
|
|
+ countStyles[size] = createCountPointStyle(size)
|
|
|
+ }
|
|
|
+ return countStyles[size]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 在地图上设置一个标注。
|
|
|
*
|
|
@@ -282,13 +392,20 @@
|
|
|
center: fromLonLat([104.912777, 34.730746]),
|
|
|
zoom: 2
|
|
|
}),
|
|
|
+ interactions: defaults({
|
|
|
+ dragPan: {
|
|
|
+ duration: 100
|
|
|
+ }
|
|
|
+ }),
|
|
|
controls: []
|
|
|
})
|
|
|
const vlText = setMark('text', { text: '中华人民共和国' })
|
|
|
const vlImg = []
|
|
|
- mapData.value.forEach((item) => {
|
|
|
- vlImg.push(setMark('img', { src: videoIcon, ...item }, [item.longitude, item.latitude]))
|
|
|
- })
|
|
|
+ const points = createPointsByRange(100)
|
|
|
+ // mapData.value.forEach((item) => {
|
|
|
+ // vlImg.push(setMark('img', { src: videoIcon, ...item }, [item.longitude, item.latitude]))
|
|
|
+ // })
|
|
|
+ const clusters = createCluster(points)
|
|
|
// 缩放显示隐藏层级
|
|
|
const zoomChange = function (e) {
|
|
|
var zoom = parseInt(map.value.getView().getZoom()) //获取当前地图的缩放级别
|
|
@@ -330,18 +447,21 @@
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
- map.value.on('singleclick', function (e) {
|
|
|
- console.log(e.coordinate)
|
|
|
- if (map.value.hasFeatureAtPixel(e.pixel)) {
|
|
|
- var feature = map.value.getFeaturesAtPixel(e.pixel)
|
|
|
- console.log(feature)
|
|
|
- feature.forEach((item) => {
|
|
|
- if (mapData.value.find((v) => item.get('name') === v.name)) {
|
|
|
+ map.value.on('click', (e) => {
|
|
|
+ clusters.getFeatures(e.pixel).then((clickedFeatures) => {
|
|
|
+ if (clickedFeatures.length) {
|
|
|
+ // Get clustered Coordinates
|
|
|
+ const features = clickedFeatures[0].get('features')
|
|
|
+ console.log(features)
|
|
|
+ if (features.length > 1) {
|
|
|
+ const extent = boundingExtent(features.map((r) => r.getGeometry().getCoordinates()))
|
|
|
+ map.value.getView().fit(extent, { duration: 1000, padding: [50, 50, 50, 50] })
|
|
|
+ } else {
|
|
|
console.log('点击了坐标点')
|
|
|
useHomeStore.temp = 'video'
|
|
|
}
|
|
|
- })
|
|
|
- }
|
|
|
+ }
|
|
|
+ })
|
|
|
})
|
|
|
map.value.getView().on('change:resolution', zoomChange)
|
|
|
zoomChange()
|