import { LayerView, proj4 } from '@mapgis/webclient-common'
import * as L from '@mapgis/leaflet'
// eslint-disable-next-line import/no-extraneous-dependencies
import { mapboxCustomCRS } from './support/mapbox/mapboxCustomUtil'
// 添加leaflet和mapbox兼容插件
// eslint-disable-next-line import/extensions
import leafletMapbox from './support/mapbox/leafletMapbox.js'
import LeafletPlugin from '../util/LeafletPlugin'
function setLayerOpacity(map, opacity) {
if (!map) return
const canvas = map.getCanvas()
if (canvas) {
canvas.style.opacity = opacity
}
}
function setLayerVisible(layer, style, visible) {
// link https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#layout-line-visibility
layer.sublayers.forEach((sublayer) => {
style.setLayoutProperty(
sublayer.id,
'visibility',
visible ? 'visible' : 'none'
)
})
}
function processStyle(mapboxMap, layerUpdateCotent, layer, innerLayer) {
if (mapboxMap[layerUpdateCotent.name]) {
// eslint-disable-next-line prefer-spread
mapboxMap[layerUpdateCotent.name].apply(mapboxMap, layerUpdateCotent.params)
return
}
switch (layerUpdateCotent.name) {
case 'setPaintProperties': {
const style = mapboxMap.style
const args = layerUpdateCotent.params
// 解析paint style 此参数键值对
const keys = Object.keys(args[1])
const layerId = args[0]
keys.forEach((key) => {
style.setPaintProperty(layerId, key, args[1][key])
})
// 触发更新
if (mapboxMap._update) {
mapboxMap._update(true)
}
break
}
case 'setLayoutProperties': {
const style = mapboxMap.style
const args = layerUpdateCotent.params
// 解析layout style 此参数键值对
const keys = Object.keys(args[1])
const layerId = args[0]
keys.forEach((key) => {
style.setLayoutProperty(layerId, key, args[1][key])
})
// 触发更新
if (mapboxMap._update) {
mapboxMap._update(true)
}
break
}
case 'setStyleLayer': {
mapboxMap.setStyle(layer.style)
break
}
case 'deleteStyleLayer': {
mapboxMap.setStyle(layer.style)
break
}
case 'setStyleLayerFilter': {
const args = layerUpdateCotent.params
mapboxMap.setFilter(args[0], args[1])
break
}
case 'setStyleLayerZoomRange': {
const args = layerUpdateCotent.params
mapboxMap.setLayerZoomRange(args[0], args[1], args[2])
break
}
case 'opacity': {
const args = layerUpdateCotent.params
// 解析layout style 此参数键值对
const opacity = args[0]
setLayerOpacity(mapboxMap, opacity)
// 触发更新
if (mapboxMap._update) {
mapboxMap._update(true)
}
break
}
case 'visible': {
const style = mapboxMap.style
const args = layerUpdateCotent.params
// 解析layout style 此参数键值对
const visible = args[0]
setLayerVisible(layer, style, visible)
// 触发更新
if (mapboxMap._update) {
mapboxMap._update(true)
}
break
}
case 'clippingArea': {
const args = layerUpdateCotent.params
// 解析layout style 此参数键值对
const clippingArea = args[0]
innerLayer.setClippingArea(
LeafletPlugin.convertClippingArea(clippingArea)
)
break
}
default: {
break
}
}
}
function applyVectorTileStyle(mapboxMap, layerUpdateCotent, layer, innerLayer) {
if (layerUpdateCotent) {
if (mapboxMap._loaded) {
processStyle(mapboxMap, layerUpdateCotent, layer, innerLayer)
} else {
mapboxMap.once('load', () => {
processStyle(mapboxMap, layerUpdateCotent, layer, innerLayer)
})
}
}
}
class ArcGISVectorTileLayerView extends LayerView {
/**
* 添加图层视图
* @param {LayerEvent} 图层事件
* @return {Promise<LayerView>} 图层视图
*/
onAdd(event) {
const layer = this.layer
const innerView = this.innerView
const _options = {
style: JSON.parse(JSON.stringify(layer.style)),
noWrap: true,
// 初始化裁剪区
clippingArea: LeafletPlugin.convertClippingArea(layer.clippingArea)
}
if (layer.tokenValue) {
_options.accessToken = layer.tokenValue
}
let mapboxgl
if (typeof module === 'object') {
// eslint-disable-next-line global-require
mapboxgl = require('@mapgis/mapbox-gl')
} else {
mapboxgl = window.mapboxgl
}
// 定义自定义坐标系
mapboxCustomCRS(mapboxgl, proj4)
// 构建L.mapboxGL图层
leafletMapbox(L, mapboxgl)
// 必须设置innerLayer
this.innerLayer = L.mapboxGL(_options).addTo(innerView)
this.innerLayer.commonLayerId = layer.id
const mapboxMap = this.innerLayer.getMapboxMap()
mapboxMap.once('load', () => {
// 初始化透明度和显示隐藏
setLayerVisible(layer, mapboxMap.style, layer._visible)
setLayerOpacity(mapboxMap, layer._opacity)
// 触发更新
if (mapboxMap._update) {
mapboxMap._update(true)
}
})
return Promise.resolve(this)
}
/**
* 移除图层视图
* @param {LayerEvent} 图层事件
* @return {Promise<LayerView>} 图层视图
*/
onRemove(event) {
this.innerView.removeLayer(this.innerLayer)
return Promise.resolve(this)
}
/**
* 更新图层视图
* @param {LayerViewUpdateEvent} 图层事件
* @return {Promise<LayerView>} 图层视图
*/
onUpdate(event) {
const _layer = this.innerLayer
const layer = this.layer
// 更新样式
if (event.updateContent && _layer && _layer.getMapboxMap) {
const mapboxMap = _layer.getMapboxMap()
event.updateContent.forEach((layerUpdateCotent) => {
applyVectorTileStyle(mapboxMap, layerUpdateCotent, layer, _layer)
})
}
return Promise.resolve(this)
}
}
export default ArcGISVectorTileLayerView