|
|
|
import React, { useEffect, useRef } from 'react'
|
|
|
|
import ReactDOMServer from 'react-dom/server'
|
|
|
|
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'
|
|
|
|
import { Popup, useMap } from 'react-leaflet'
|
|
|
|
import { Button, Col, Row } from 'reactstrap'
|
|
|
|
const PopElement = () => {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Row>
|
|
|
|
<Col>
|
|
|
|
<h3>Hallo</h3>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
<Row>
|
|
|
|
<Col>
|
|
|
|
<Button id="tombol">TEST</Button>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const VectorGridd = createTileLayerComponent(
|
|
|
|
function createTileLayer(props, context) {
|
|
|
|
const highlight = useRef(null)
|
|
|
|
const active = useRef(null)
|
|
|
|
const map = useMap()
|
|
|
|
const {
|
|
|
|
data,
|
|
|
|
style,
|
|
|
|
hoverStyle,
|
|
|
|
activeStyle,
|
|
|
|
onPopupOpen,
|
|
|
|
onClick,
|
|
|
|
onMouseover,
|
|
|
|
onMouseout,
|
|
|
|
onDblclick,
|
|
|
|
onContextmenu,
|
|
|
|
vectorTileLayerStyles,
|
|
|
|
url,
|
|
|
|
maxNativeZoom,
|
|
|
|
subdomains,
|
|
|
|
accessKey,
|
|
|
|
accessToken,
|
|
|
|
type = 'protobuf',
|
|
|
|
interactive = true,
|
|
|
|
idField = '',
|
|
|
|
...rest
|
|
|
|
} = props
|
|
|
|
delete rest.leaflet
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
console.log({ vectorGrid })
|
|
|
|
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
|
|
|
|
}
|
|
|
|
)
|
|
|
|
// vectorGrid.bindTooltip(
|
|
|
|
// (layer) => {
|
|
|
|
// const id = _getFeatureId(layer)
|
|
|
|
// return id
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// sticky: true,
|
|
|
|
// direction: 'auto',
|
|
|
|
// className: tooltipClassName
|
|
|
|
// }
|
|
|
|
// )
|
|
|
|
}
|
|
|
|
if (popup) {
|
|
|
|
// console.log({ vectorGrid })
|
|
|
|
// vectorGrid.bindPopup(popup)
|
|
|
|
// vectorGrid.bindPopup((layer) => {
|
|
|
|
// // console.log({ a, b })
|
|
|
|
// if (isFunction(popup)) {
|
|
|
|
// return popup(layer)
|
|
|
|
// } else if (isString(toopopupltip) && has(layer.properties, popup)) {
|
|
|
|
// return String(layer.properties[popup])
|
|
|
|
// } else if (isString(popup)) {
|
|
|
|
// return popup
|
|
|
|
// }
|
|
|
|
// return ''
|
|
|
|
// })
|
|
|
|
}
|
|
|
|
}, [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)) {
|
|
|
|
// console.log(feature.properties[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) => {
|
|
|
|
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 lat_lng = new L.LatLng(properties.GEO_LOK_LAT, properties.GEO_LOK_LING)
|
|
|
|
|
|
|
|
// (Number(properties.GEO_LOK_LING), Number(properties.GEO_LOK_LAT))
|
|
|
|
const featureId = _getFeatureId(e.layer)
|
|
|
|
// console.log({ properties, featureId })
|
|
|
|
// console.log(e.layer)
|
|
|
|
// console.log(properties)
|
|
|
|
_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)
|
|
|
|
}
|
|
|
|
//json get Detail
|
|
|
|
L.popup()
|
|
|
|
.setLatLng(lat_lng)
|
|
|
|
.setContent(ReactDOMServer.renderToString(<PopElement />))
|
|
|
|
// .setContent(useRenderPopup({}))
|
|
|
|
.openOn(map)
|
|
|
|
})
|
|
|
|
.on('dblclick', (e) => {
|
|
|
|
_propagateEvent(onDblclick, e)
|
|
|
|
clearActive()
|
|
|
|
})
|
|
|
|
.on('contextmenu', (e) => {
|
|
|
|
_propagateEvent(onContextmenu, e)
|
|
|
|
clearActive()
|
|
|
|
})
|
|
|
|
|
|
|
|
map.on('popupopen', () => {
|
|
|
|
console.log('mapopenpopup')
|
|
|
|
})
|
|
|
|
return {
|
|
|
|
instance: vectorGrid,
|
|
|
|
context
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function upgrade(layer, props, prevprops) {
|
|
|
|
return updateGridLayer(layer, props, prevprops)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
export default VectorGridd
|