import { useEffect, useRef } from 'react' import { createTileLayerComponent, updateGridLayer } from '@react-leaflet/core' import L from 'leaflet' import isObject from 'lodash/isObject' import isFunction from 'lodash/isFunction' import isString from 'lodash/isString' import isEmpty from 'lodash/isEmpty' import clone from 'lodash/clone' import cloneDeep from 'lodash/cloneDeep' import extend from 'lodash/extend' import merge from 'lodash/merge' import has from 'lodash/has' import find from 'lodash/find' import 'leaflet.vectorgrid' import './L.VectorGrid.VectorPoi' export const VectorGridd = createTileLayerComponent( function createTileLayer(props, context) { const highlight = useRef(null) const active = useRef(null) const { data, style, hoverStyle, activeStyle, onClick, onMouseover, onMouseout, onDblclick, onContextmenu, vectorTileLayerStyles, url, maxNativeZoom, subdomains, accessKey, accessToken, type = 'protobuf', interactive = true, idField = '', ...rest } = props delete rest.leaflet useEffect(() => { const { tooltipClassName = '', tooltip = null, popup = null } = props if (tooltip) { vectorGrid.bindTooltip( (layer) => { if (isFunction(tooltip)) { return tooltip(layer) } else if (isString(tooltip) && has(layer.properties, tooltip)) { return String(layer.properties[tooltip]) } else if (isString(tooltip)) { return tooltip } return '' }, { sticky: true, direction: 'auto', className: tooltipClassName } ) } if (popup) { vectorGrid.bindPopup(popup) } }, [props.tooltip, props.popup]) const baseStyle = (properties, zoom) => { if (isFunction(style)) { return style(properties) } else if (isObject(style)) { return style } return { weight: 0.5, opacity: 1, color: '#ccc', fillColor: '#390870', fillOpacity: 0.6, fill: true, stroke: true } } const _getFeatureId = (feature) => { const { idField } = props if (isFunction(idField)) { return idField(feature) } else if (isString(idField)) { return feature.properties[idField] } } const setFeatureStyle = (id, style) => { vectorGrid.setFeatureStyle(id, style) } const resetFeatureStyle = (id) => { vectorGrid.resetFeatureStyle(id) } const clearHighlight = (properties) => { if (highlight.current) { if (highlight.current !== active.current) { resetFeatureStyle(highlight.current) } else { let st if (isFunction(activeStyle)) { st = activeStyle(properties) } else if (isObject(activeStyle)) { st = cloneDeep(activeStyle) } if (!isEmpty(st)) { const base = cloneDeep(baseStyle(properties)) const activeStyle = extend(base, st) setFeatureStyle(active.current, activeStyle) } } } highlight.current = null } const clearActive = () => { if (active.current) { resetFeatureStyle(active.current) } active.current = null } const getFeature = (featureId) => { const { data, idField } = props if (isEmpty(data) || isEmpty(data.features)) return {} const feature = find(data.features, ({ properties }) => properties[idField] === featureId) return cloneDeep(feature) } const _propagateEvent = (eventHandler, e) => { if (!isFunction(eventHandler)) return const featureId = _getFeatureId(e.layer) const feature = getFeature(featureId) const event = cloneDeep(e) const mergedEvent = merge(event.target, { feature }) eventHandler(event) } let vectorGrid if (type === 'slicer') { vectorGrid = new L.vectorGrid.slicer(data, { interactive: interactive, getFeatureId: (feature) => _getFeatureId(feature), rendererFactory: L.svg.tile, vectorTileLayerStyles: vectorTileLayerStyles || { sliced: (properties, zoom) => { const bs = baseStyle(properties, zoom) bs.fill = true bs.stroke = true return bs } }, ...rest }) } else { vectorGrid = new L.vectorGrid.vectorpoi(url, { interactive: interactive, key: accessKey, token: accessToken, vectorTileLayerStyles: vectorTileLayerStyles, getFeatureId: (feature) => _getFeatureId(feature), rendererFactory: L.svg.tile, ...rest }) } vectorGrid // .on('mouseover', (e) => { // console.log(e) // const { properties } = e.layer // _propagateEvent(onMouseover, e) // let st // const featureId = _getFeatureId(e.layer) // if (isFunction(hoverStyle)) { // st = hoverStyle(properties) // } else if (isObject(hoverStyle)) { // st = cloneDeep(hoverStyle) // } // if (!isEmpty(st) && featureId) { // clearHighlight(properties) // highlight.current = featureId // const base = cloneDeep(baseStyle(properties)) // const hoverStyle = extend(base, st) // setFeatureStyle(featureId, hoverStyle) // } // }) // .on('mouseout', (e) => { // const { properties } = e.layer // _propagateEvent(onMouseout, e) // clearHighlight(properties) // }) // .on('click', (e) => { // const { properties } = e.layer // const featureId = _getFeatureId(e.layer) // _propagateEvent(onClick, e) // let st // if (isFunction(activeStyle)) { // st = activeStyle(properties) // } else if (isObject(activeStyle)) { // st = cloneDeep(activeStyle) // } // if (!isEmpty(st) && featureId) { // clearActive() // active.current = featureId // const base = cloneDeep(baseStyle(properties)) // const activeStyle = extend(base, st) // setFeatureStyle(featureId, activeStyle) // } // }) // .on('dblclick', (e) => { // _propagateEvent(onDblclick, e) // clearActive() // }) .on('contextmenu', (e) => { _propagateEvent(onContextmenu, e) clearActive() }) return { instance: vectorGrid, context } }, function upgrade(layer, props, prevprops) { return updateGridLayer(layer, props, prevprops) } ) export default VectorGridd