import * as L from '@mapgis/leaflet'
import { FeatureRender, GeometryType } from '@mapgis/webclient-common'
import {
convertFeature,
createGraphic,
updatePolylineMarkers,
updateMultiPolylineMarkers,
getAreaCoords
} from './convertFeatureToLeafletGraphicUtil'
import ConvertGeometryUtil from './ConvertGeometryUtil'
import ConvertSymbolUtil from './ConvertSymbolUtil'
import LeafletPlugin from './LeafletPlugin'
const toLeafletStyle = ConvertSymbolUtil.convertSymboltoLeafletStyle
class LeafletFeatureRender extends FeatureRender {
/**
* @description: 绘制要素
* @param {*} innerLayer
* @param {*} features
* @return {*}
*/
drawFeature(innerLayer, features) {
if (innerLayer) {
const { layerVisible, layerOpacity } = innerLayer
features.forEach((feature) => {
if (feature.visible) {
// 异步添加
const graphic = convertFeature(feature)
// 绑定id,leaflet内部处理了id方式,为保持逻辑一致
graphic['commonFeatureId'] = feature.id
// 设置图层id
graphic['commonLayerId'] = innerLayer.commonLayerId
// 设置图层透明度和显隐
LeafletPlugin.setGraphicVisibleOpacity(
graphic,
layerOpacity,
layerVisible
)
innerLayer.addLayer(graphic)
}
})
}
}
/**
* @description: 更新样式
* @param {Object} innerLayer
* @param {Array<Feature>} features
* @param {Array<Object>} updateDetail 要素更新细节
* @return {*}
*/
updateFeature(innerLayer, features, updateDetail) {
if (innerLayer) {
super.updateFeature(innerLayer, features, updateDetail)
features.forEach((feature, i) => {
const detail = updateDetail[i]
if (!detail || !feature) return
this._update(
innerLayer,
detail.symbolUpdated,
detail.geometryUpdated,
feature
)
})
}
}
/**
* @description: 更新几何
* @param {*} innerLayer
* @param {*} geometryUpdated
* @param {*} feature
* @return {*}
*/
_update(innerLayer, symbolUpdated, geometryUpdated, feature) {
const geometry = feature.geometry
const symbol = feature.symbol
const isGeometryUpdate = !!geometryUpdated
const isSymbolUpdate = !!symbolUpdated
let isRedraw = false
const graphic = this._getGraphicByFeatureId(innerLayer, feature.id)
// 处理要素刷新机制
const visible = feature.visible
if (!visible) {
this.clearFeature(innerLayer, [feature])
return
}
// 几何图形
if (!graphic) {
this.drawFeature(innerLayer, [feature])
return
}
// 处理切换符号的机制
if (symbolUpdated) {
const { key, oldValue, value } = symbolUpdated
if (oldValue && value && oldValue.type !== value.type) {
isRedraw = true
}
if (key === 'type') {
isRedraw = true
}
}
if (!isRedraw) {
switch (geometry.type) {
case GeometryType.point: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol) || {}
graphic.setStyle(leafletStyle)
}
if (isGeometryUpdate) {
const latlngs = ConvertGeometryUtil.toLeafletCoords(geometry)
graphic.setLatLng(latlngs[0])
}
break
}
case GeometryType.multiPoint: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
graphic.eachLayer((layer) => {
layer.setStyle(leafletStyle)
})
}
if (isGeometryUpdate) {
const latlngs = ConvertGeometryUtil.toLeafletCoords(geometry)
const keys = Object.keys(graphic._layers)
const layers = keys.map((key) => graphic._layers[key]) || []
const latlngsNum = latlngs.length
let len = layers.length
// 更新多点
if (len !== latlngsNum) {
if (len > latlngsNum) {
while (len !== latlngsNum) {
graphic.removeLayer(layers[len - 1])
len -= 1
}
let i = 0
graphic.eachLayer((layer) => {
layer.setLatLng(latlngs[i])
i += 1
})
} else {
const symbolType = feature.symbol.type
const style = toLeafletStyle(feature.symbol)
latlngs.forEach((latlng, i) => {
if (i < len) {
layers[i].setLatLng(latlng)
} else {
const marker = createGraphic(symbolType, latlng, style)
graphic.addLayer(marker)
}
})
}
} else {
let i = 0
graphic.eachLayer((layer) => {
layer.setLatLng(latlngs[i])
i += 1
})
}
}
break
}
case GeometryType.lineString: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
if (graphic['__line__graphic']) {
graphic['__line__graphic'].setStyle(leafletStyle)
}
}
if (isGeometryUpdate) {
const latlngs = ConvertGeometryUtil.toLeafletCoords(geometry)
if (graphic['__line__graphic']) {
graphic['__line__graphic'].setLatLngs(latlngs)
}
}
if (symbol.marker) {
updatePolylineMarkers(feature, graphic)
}
break
}
case GeometryType.multiLineString: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
if (graphic['__line__graphic']) {
graphic['__line__graphic'].setStyle(leafletStyle)
}
}
if (isGeometryUpdate) {
const latlngs = ConvertGeometryUtil.toLeafletCoords(geometry)
if (graphic['__line__graphic']) {
graphic['__line__graphic'].setLatLngs(latlngs)
}
}
if (symbol.marker) {
updateMultiPolylineMarkers(feature, graphic)
}
break
}
case GeometryType.multiPolygon:
case GeometryType.polygon: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
graphic.setStyle(leafletStyle)
}
if (isGeometryUpdate) {
const latlngs = getAreaCoords(symbol.type, geometry, feature)
if (graphic.setLatLngs) {
graphic.setLatLngs(latlngs)
} else if (graphic.setLatLng) {
graphic.setLatLng(latlngs)
}
}
break
}
case GeometryType.extent: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
graphic.setStyle(leafletStyle)
}
if (isGeometryUpdate) {
const latlngs = getAreaCoords(symbol.type, geometry, feature)
if (graphic instanceof L.Rectangle) {
graphic.setBounds(L.latLngBounds(latlngs[0], latlngs[1]))
} else if (graphic.setLatLngs) {
graphic.setLatLngs(latlngs)
} else if (graphic.setLatLng) {
graphic.setLatLng(latlngs)
}
}
break
}
case GeometryType.circle: {
if (isSymbolUpdate) {
const leafletStyle = toLeafletStyle(feature.symbol)
graphic.setStyle(leafletStyle)
}
if (isGeometryUpdate) {
const latlngs = getAreaCoords(
symbol.type,
geometry.toPolygon(),
feature
)
if (graphic.setLatLngs) {
graphic.setLatLngs(latlngs)
} else if (graphic.setLatLng) {
graphic.setLatLng(latlngs)
}
}
break
}
default: {
break
}
}
}
// 重新绘制
if (isRedraw) {
this._redrawFeature(innerLayer, feature)
}
}
/**
* @description: 清除要素
* @param {*} innerLayer
* @param {*} features
* @return {*}
*/
clearFeature(innerLayer, features) {
if (innerLayer) {
super.clearFeature(innerLayer, features)
features.forEach((feature) => {
const _graphic = this._getGraphicByFeatureId(innerLayer, feature.id)
if (_graphic) {
innerLayer.removeLayer(_graphic)
}
})
}
}
/**
* @description: 清空上下文图层
* @param {*} innerLayer
* @return {*}
*/
clear(innerLayer) {
if (innerLayer) {
super.clear(innerLayer)
innerLayer.clearLayers()
}
}
/**
* @description: 根据要素id获取引擎图元对象
* @param {String} featureId
* @return {Object}
*/
_getGraphicByFeatureId(innerLayer, featureId) {
let _graphic = null
if (innerLayer && featureId) {
innerLayer.eachLayer((graphic) => {
if (graphic['commonFeatureId'] === featureId) {
_graphic = graphic
return _graphic
}
})
}
return _graphic
}
_redrawFeature(innerLayer, feature) {
// 类型不一致,重绘
this.clearFeature(innerLayer, [feature])
this.drawFeature(innerLayer, [feature])
}
}
export default LeafletFeatureRender