|
@@ -28,12 +28,23 @@
|
|
|
</template>
|
|
|
</el-tree-v2>
|
|
|
</div>
|
|
|
- <div class="map">
|
|
|
+ <div class="map-block">
|
|
|
<EasyMapComponent
|
|
|
class="map"
|
|
|
layout="info"
|
|
|
@easyMapLoad="mapLoad"
|
|
|
/>
|
|
|
+ <div class="hide-list">
|
|
|
+ <div class="hover-main">
|
|
|
+ <template v-for="(item, index) in polyLineHideList">
|
|
|
+ <div class="hover-item">
|
|
|
+ <div class="hover-item-label __hover" @click="webglPolyLineLayer.getSource().addFeature(item.feature), polyLineHideList.splice(index, 1)">恢复:</div>
|
|
|
+ <div class="hover-item-value">{{item.name}}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div ref="ref_mapHover" class="hover-info">
|
|
|
<div class="hover-main">
|
|
@@ -47,6 +58,25 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="hover-info" ref="ref_mapClick" style="z-index: 10">
|
|
|
+ <div class="hover-info-head">
|
|
|
+ <span>要素列表</span>
|
|
|
+ </div>
|
|
|
+ <div class="hover-info-close __hover" @click="mapClick.overlay?.setPosition(undefined)">
|
|
|
+ <img src="@/components/easyMap/images/close.png" alt=""/>
|
|
|
+ </div>
|
|
|
+ <div class="hover-main" v-if="mapClick.list" style="max-height: 250px;overflow-y: auto;">
|
|
|
+ <template v-for="item in mapClick.list">
|
|
|
+ <div class="hover-item">
|
|
|
+ <div class="hover-item-label">{{item.type}}:</div>
|
|
|
+ <div class="hover-item-value">
|
|
|
+ {{item.name}}
|
|
|
+ <el-link href="javascript:;" type="danger" @click.stop="onActive(item)">突出</el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -74,10 +104,15 @@ import * as layer from "ol/layer";
|
|
|
import * as format from "ol/format";
|
|
|
import * as ol from "ol";
|
|
|
import WebGLVectorLayerRenderer from 'ol/renderer/webgl/VectorLayer';
|
|
|
+import * as ElementStyle from "./elementStyle";
|
|
|
+import * as turf from '@turf/turf'
|
|
|
+import * as style from "ol/style";
|
|
|
+
|
|
|
|
|
|
class WebGLLayer extends layer.Layer {
|
|
|
createRenderer() {
|
|
|
return new WebGLVectorLayerRenderer(this, {
|
|
|
+ disableHitDetection: false,
|
|
|
style: {
|
|
|
'stroke-color': ['*', ['get', 'lineColor'], [220, 220, 220]],
|
|
|
'stroke-width': ['get', 'lineWidth'],
|
|
@@ -102,13 +137,21 @@ export default defineComponent({
|
|
|
treeText: '',
|
|
|
webglPointLayer: <any>null,
|
|
|
webglPolyLineLayer: <any>null,
|
|
|
+ radarLayer: <any>null,
|
|
|
+ polyLineActiveLayer: <any>null,
|
|
|
mapHover: {
|
|
|
info: {},
|
|
|
overlay: <any>null
|
|
|
- }
|
|
|
+ },
|
|
|
+ mapClick: {
|
|
|
+ list: {},
|
|
|
+ overlay: <any>null
|
|
|
+ },
|
|
|
+ polyLineHideList: <any>[]
|
|
|
})
|
|
|
const ref_tree = ref()
|
|
|
const ref_mapHover = ref()
|
|
|
+ const ref_mapClick = ref()
|
|
|
const mapLoad = (map, func) => {
|
|
|
state.map = map
|
|
|
state.mapFunc = func
|
|
@@ -122,12 +165,12 @@ export default defineComponent({
|
|
|
mapId: key,
|
|
|
mapLabel: pName,
|
|
|
children: [],
|
|
|
- _show: true
|
|
|
+ _show: key !== 'radarList'
|
|
|
}
|
|
|
xqysJson.data[key].forEach(v => {
|
|
|
v.mapId = key + '_' + v[idKey]
|
|
|
v.mapLabel = v[labelKey]
|
|
|
- v._show = true
|
|
|
+ v._show = key !== 'radarList'
|
|
|
obj.children.push(v)
|
|
|
})
|
|
|
state.treeData.push(obj)
|
|
@@ -150,6 +193,27 @@ export default defineComponent({
|
|
|
setSourceData()
|
|
|
}
|
|
|
const initMap = () => {
|
|
|
+ state.radarLayer = new layer.Vector({
|
|
|
+ zIndex: 40,
|
|
|
+ })
|
|
|
+ state.map.addLayer(state.radarLayer)
|
|
|
+ state.polyLineActiveLayer = new layer.Vector({
|
|
|
+ zIndex: 39,
|
|
|
+ source: new source.Vector(),
|
|
|
+ style: (feat: any) => {
|
|
|
+ feat.setStyle(new style.Style({
|
|
|
+ stroke: new style.Stroke({
|
|
|
+ color: '#ff0000',
|
|
|
+ width: feat.get('lineWidth'),
|
|
|
+ lineDash: feat.get('lineDasharray')
|
|
|
+ }),
|
|
|
+ fill: new style.Fill({
|
|
|
+ color: 'rgba(255,0,0,0.3)',
|
|
|
+ }),
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.map.addLayer(state.polyLineActiveLayer)
|
|
|
state.mapHover.overlay = new ol.Overlay({
|
|
|
id: 'ref_mapHover',
|
|
|
element: ref_mapHover.value,
|
|
@@ -162,14 +226,35 @@ export default defineComponent({
|
|
|
}
|
|
|
})
|
|
|
state.map.addOverlay(state.mapHover.overlay)
|
|
|
+ state.mapClick.overlay = new ol.Overlay({
|
|
|
+ id: 'ref_mapClick',
|
|
|
+ element: ref_mapClick.value,
|
|
|
+ autoPan: false,
|
|
|
+ offset: [0, -30],
|
|
|
+ positioning: 'bottom-center',
|
|
|
+ stopEvent: true,
|
|
|
+ insertFirst: false,
|
|
|
+ autoPanAnimation: {
|
|
|
+ duration: 250
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.map.addOverlay(state.mapClick.overlay)
|
|
|
state.map.on('pointermove', function (evt) {
|
|
|
if (evt.dragging) {
|
|
|
return;
|
|
|
}
|
|
|
const pixel = state.map.getEventPixel(evt.originalEvent);
|
|
|
- const feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
|
|
|
+ let feature: any = state.map.forEachFeatureAtPixel(pixel, function (feature) {
|
|
|
return feature;
|
|
|
});
|
|
|
+ const point = state.map.forEachFeatureAtPixel(pixel, function (feature) {
|
|
|
+ if (feature.get('geomType') === 'Point') {
|
|
|
+ return feature;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (point) {
|
|
|
+ feature = point
|
|
|
+ }
|
|
|
if (feature) {
|
|
|
state.mapHover.info = {
|
|
|
name: feature.get('name'),
|
|
@@ -180,8 +265,58 @@ export default defineComponent({
|
|
|
state.mapHover.overlay.setPosition(undefined)
|
|
|
}
|
|
|
});
|
|
|
+ state.map.on('contextmenu', function (evt) {
|
|
|
+ evt.preventDefault()
|
|
|
+ if (evt.dragging) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const pixel = state.map.getEventPixel(evt.originalEvent);
|
|
|
+ const feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
|
|
|
+ return feature;
|
|
|
+ });
|
|
|
+ if (feature?.getGeometry().getType() !== 'Point') {
|
|
|
+ state.mapHover.overlay.setPosition(undefined)
|
|
|
+ state.webglPolyLineLayer.getSource().removeFeature(feature)
|
|
|
+ state.polyLineHideList.push({
|
|
|
+ name: feature.get('name'),
|
|
|
+ feature: feature
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.map.on('singleclick', function (evt) {
|
|
|
+ if (evt.dragging) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const feats: any = []
|
|
|
+ state.webglPolyLineLayer.getSource().getFeatures().forEach(v => {
|
|
|
+ if (v.get('geomType') === 'Polygon') {
|
|
|
+ const poly = turf.polygon(v.getGeometry().getCoordinates());
|
|
|
+ if (turf.booleanPointInPolygon(turf.point(evt.coordinate), poly)) {
|
|
|
+ feats.push(v)
|
|
|
+ }
|
|
|
+ } else if (v.get('geomType') === 'LineString') {
|
|
|
+ const circle = turf.circle(evt.coordinate, 0.5, {steps: 4, units: 'kilometers', properties: {foo: 'bar'}})
|
|
|
+ const line = turf.lineString(v.getGeometry().getCoordinates());
|
|
|
+ if (turf.booleanCrosses(circle, line)) {
|
|
|
+ feats.push(v)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (feats.length > 0) {
|
|
|
+ state.mapClick.list = feats.map(v => {
|
|
|
+ return {
|
|
|
+ name: v.get('name'),
|
|
|
+ type: v.get('geomType'),
|
|
|
+ feature: v
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.mapClick.overlay.setPosition(evt.coordinate)
|
|
|
+ } else {
|
|
|
+ state.mapClick.overlay.setPosition(undefined)
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
- const style = {
|
|
|
+ const webglStyle = {
|
|
|
'icon-src': jlt,
|
|
|
'icon-width': 800,
|
|
|
'icon-height': 600,
|
|
@@ -209,13 +344,88 @@ export default defineComponent({
|
|
|
const setSourceData = () => {
|
|
|
const points: any = []
|
|
|
const polyLines: any = []
|
|
|
+ const radars: any = []
|
|
|
state.treeData.forEach(p => {
|
|
|
if (p.mapId === 'deptInfo') {
|
|
|
+ p.children.forEach(v => {
|
|
|
+ if (v._show) {
|
|
|
+ try {
|
|
|
+ if (v.pointCoordinate) {
|
|
|
+ const feat: any = new format.WKT().readFeature(v.pointCoordinate)
|
|
|
+ feat.set('layerType', 'webgl')
|
|
|
+ feat.set('name', p.mapLabel + '_' + v.mapLabel)
|
|
|
+ feat.set('geomType', feat.getGeometry().getType())
|
|
|
+ feat.set('iconImage', 'radarListImg')
|
|
|
+ points.push(feat)
|
|
|
+ }
|
|
|
+ if (v.regionalLocation) {
|
|
|
+ const feat: any = new format.WKT().readFeature(v.regionalLocation)
|
|
|
+ feat.set('layerType', 'webgl')
|
|
|
+ feat.set('name', p.mapLabel + '_' + v.mapLabel)
|
|
|
+ feat.set('geomType', feat.getGeometry().getType())
|
|
|
+ let fillColor = 'rgba(20, 129, 241, 0.3)'
|
|
|
+ let lineColor = '#2860F1'
|
|
|
+ let lineWidth = 1
|
|
|
+ let lineDasharray = globalLineDash[0]
|
|
|
+ if (v.regionalColor) {
|
|
|
+ fillColor = v.regionalColor
|
|
|
+ }
|
|
|
+ if (v.segmentColor) {
|
|
|
+ lineColor = v.segmentColor
|
|
|
+ }
|
|
|
+ if (v.segmentWidth) {
|
|
|
+ lineWidth = v.segmentWidth
|
|
|
+ }
|
|
|
+ if (v.segmentType) {
|
|
|
+ lineDasharray = globalLineDash[Number(v.segmentType)]
|
|
|
+ }
|
|
|
+ feat.set('fillColor', fillColor)
|
|
|
+ feat.set('lineColor', lineColor)
|
|
|
+ feat.set('lineWidth', lineWidth)
|
|
|
+ feat.set('lineDasharray', lineDasharray)
|
|
|
+ polyLines.push(feat)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else if (p.mapId === 'radarList') {
|
|
|
+ p.children.forEach(v => {
|
|
|
+ if (v._show) {
|
|
|
+ try {
|
|
|
+ if (v.location) {
|
|
|
+ const feat: any = new format.WKT().readFeature(v.location)
|
|
|
+ feat.set('name', p.mapLabel + '_' + v.mapLabel)
|
|
|
+ feat.set('geomType', feat.getGeometry().getType())
|
|
|
+ feat.setStyle(ElementStyle.radarPoint())
|
|
|
+ radars.push(feat)
|
|
|
+ }
|
|
|
+ if (v.radarShielding?.length > 0) {
|
|
|
+ v.radarShielding.forEach(s => {
|
|
|
+ const feat: any = new format.WKT().readFeature(s.location)
|
|
|
+ feat.set('name', p.mapLabel + '_' + v.mapLabel + '_' + s.name)
|
|
|
+ feat.set('geomType', feat.getGeometry().getType())
|
|
|
+ feat.setStyle(ElementStyle.radarArea(s, state.map))
|
|
|
+ radars.push(feat)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (Number(v.scannedAreaEnd) > 0) {
|
|
|
+ const feat: any = new format.WKT().readFeature(v.location)
|
|
|
+ feat.set('name', p.mapLabel + '_' + v.mapLabel + '_半径')
|
|
|
+ feat.set('geomType', feat.getGeometry().getType())
|
|
|
+ feat.setStyle(ElementStyle.radarCircle(v, state.map))
|
|
|
+ radars.push(feat)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
} else {
|
|
|
p.children.forEach(v => {
|
|
|
if (v._show) {
|
|
|
try {
|
|
|
const feat: any = new format.WKT().readFeature(v.location)
|
|
|
+ feat.set('layerType', 'webgl')
|
|
|
feat.set('name', p.mapLabel + '_' + v.mapLabel)
|
|
|
feat.set('geomType', feat.getGeometry().getType())
|
|
|
if (feat.getGeometry().getType() === 'Point') {
|
|
@@ -257,8 +467,6 @@ export default defineComponent({
|
|
|
}
|
|
|
feat.set('fillColor', fillColor)
|
|
|
feat.set('lineColor', lineColor)
|
|
|
- feat.set('_fillColor', fillColor)
|
|
|
- feat.set('_lineColor', lineColor)
|
|
|
feat.set('lineWidth', lineWidth)
|
|
|
feat.set('lineDasharray', lineDasharray)
|
|
|
polyLines.push(feat)
|
|
@@ -274,7 +482,7 @@ export default defineComponent({
|
|
|
state.webglPolyLineLayer.dispose()
|
|
|
}
|
|
|
state.webglPolyLineLayer = new WebGLLayer({
|
|
|
- zIndex: 15,
|
|
|
+ zIndex: 20,
|
|
|
source: new source.Vector({
|
|
|
features: polyLines
|
|
|
}),
|
|
@@ -285,13 +493,19 @@ export default defineComponent({
|
|
|
state.webglPointLayer.dispose()
|
|
|
}
|
|
|
state.webglPointLayer = new layer.WebGLPoints({
|
|
|
- zIndex: 15,
|
|
|
+ zIndex: 30,
|
|
|
source: new source.Vector({
|
|
|
features: points
|
|
|
}),
|
|
|
- style: style
|
|
|
+ style: webglStyle
|
|
|
})
|
|
|
state.map.addLayer(state.webglPointLayer)
|
|
|
+ if (state.radarLayer) {
|
|
|
+ state.radarLayer.setSource(new source.Vector({
|
|
|
+ features: radars
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ state.polyLineActiveLayer?.getSource()?.clear()
|
|
|
}
|
|
|
const filterMethod = (text: string, node: any) => {
|
|
|
return node.mapLabel?.includes(text)
|
|
@@ -333,6 +547,11 @@ export default defineComponent({
|
|
|
})
|
|
|
setSourceData()
|
|
|
}
|
|
|
+ const onActive = (item) => {
|
|
|
+ state.polyLineActiveLayer.getSource().clear()
|
|
|
+ state.polyLineActiveLayer.getSource().addFeature(item.feature)
|
|
|
+ console.log(item)
|
|
|
+ }
|
|
|
onMounted(() => {
|
|
|
console.log(xqysJson)
|
|
|
// console.log(WebGLLayer)
|
|
@@ -348,7 +567,9 @@ export default defineComponent({
|
|
|
onHide,
|
|
|
onShowAll,
|
|
|
onHideAll,
|
|
|
- ref_mapHover
|
|
|
+ ref_mapHover,
|
|
|
+ ref_mapClick,
|
|
|
+ onActive
|
|
|
}
|
|
|
},
|
|
|
})
|
|
@@ -363,10 +584,76 @@ export default defineComponent({
|
|
|
width: 400px;
|
|
|
height: 100%;
|
|
|
}
|
|
|
- .map {
|
|
|
+ .map-block {
|
|
|
flex: 1;
|
|
|
+ position: relative;
|
|
|
+ .map {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ .hide-list {
|
|
|
+ $footH: 10px;
|
|
|
+ min-width: 300px;
|
|
|
+ max-height: 300px;
|
|
|
+ overflow-y: auto;
|
|
|
+ background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
|
|
|
+ border-radius: 0px 4px 4px 4px;
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ .hover-info-head {
|
|
|
+ padding: 0 4px;
|
|
|
+ height: 18px;
|
|
|
+ position: absolute;
|
|
|
+ top: -18px;
|
|
|
+ left: 0;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #FFFFFF;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ line-height: 8px;
|
|
|
+ background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
|
|
|
+ border-radius: 2px 2px 0 0;/* 设置圆角 */
|
|
|
+ >img {
|
|
|
+ margin: 0 4px 0 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .hover-info-close {
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: -16px;
|
|
|
+ }
|
|
|
+ .hover-main {
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+ padding: 10px;
|
|
|
+ .hover-item {
|
|
|
+ display: flex;
|
|
|
+ .hover-item-label {
|
|
|
+ min-width: 42px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #08FFFF;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ .hover-item-value {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #FFFFFF;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
.hover-info {
|
|
|
$footH: 10px;
|
|
|
width: 300px;
|