You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

300 lines
8.3 KiB

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