src/lib/components/molecules/svg-map/layers/Polygon.jsx (75 lines of code) (raw):

import { useContext, useEffect, useCallback, useState } from "preact/hooks" import { MapContext } from "../context/MapContext" import { dynamicPropValue } from "../helpers/dynamicPropValue" import { geoContains } from "d3-geo" import Flatbush from "flatbush" export function Polygon({ id, features, fill = null, stroke = null, strokeWidth = 1, zIndex = 0, styles, }) { const context = useContext(MapContext) const [searchIndex, setSearchIndex] = useState() useEffect(() => { if (!context.path) return let index = new Flatbush(features.length) for (const feature of features) { const bounds = context.path.bounds(feature) index.add( Math.floor(bounds[0][0]), Math.floor(bounds[0][1]), Math.ceil(bounds[1][0]), Math.ceil(bounds[1][1]), ) } index.finish() setSearchIndex(index) }, [context.path, features]) const findFeatureAtPoint = useCallback( ([x, y]) => { const projectedPoint = context.projection.invert([x, y]) // console.log('projected point', projectedPoint) const results = searchIndex.search(x, y, x, y) let found = results[0] results.forEach((idx) => { const feature = features[idx] if (geoContains(feature, projectedPoint)) { found = idx } }) return features[found] }, [context, searchIndex, features], ) useEffect(() => { const layer = { zIndex, findFeatureAtPoint, } context.registerLayer(layer) return () => { context.unregisterLayer(layer) } }, [context, zIndex, findFeatureAtPoint]) return ( <> {features.map((d, index) => { return ( <path key={index} id={dynamicPropValue(id, d, index)} className={dynamicPropValue(styles, d, index)} fill={dynamicPropValue(fill, d, index)} stroke={dynamicPropValue(stroke, d, index)} strokeWidth={dynamicPropValue(strokeWidth, d, index)} d={context.path(d)} /> ) })} </> ) }