d3.js 使用mapshaper简化GeoJson FeatureCollection会导致问题

wfveoks0  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(126)

更具体地说,它会导致相同的代码在Map上呈现轮廓,并且在使用指针事件时只识别最后一个路径元素。我在mapshaper上使用他们的网站简化了continents.json文件,并替换了我的public/data文件夹中的文件。目前,我正在一个组件中获取数据,并将其传递给另一个组件。

const WorldMapAtlas = () => {
    const [continents, continents] = useState<null | FeatureCollection>(null)

    useEffect(() => {
        fetch('data/continents_simple.json')
            .then(response => response.json())
            .then((worldData) => {
                let continents: FeatureCollection = (worldData as FeatureCollection)
                setContinents(continents)
            })
            .catch(error => console.log(error))        
    }, [])

    return (
        <>
            {continents &&
                 <div className="w-3/4" >
                     <TestMap projectionType={geoNaturalEarth1} GeoJson={continents} size={[928, 454]} translate={[464, 227]} />
                 </div>
            }
        </>
    )
}

然后我尝试使用TestMap组件呈现它

interface props {
    projectionType: () => GeoProjection;
    GeoJson: FeatureCollection | null;
    size: [number, number];
    translate: [number, number];
}

const TestMap = (props: props) => {
    const svgRef = useRef(null)
    const [height, width] = props.size;

    useEffect(() => {
        //accesses the reference element
        const svg = d3.select(svgRef.current)
 
        //declares the geoJson, projection, and path(pathGenerator)
        const geoJson = props.GeoJson
        const projection = props.projectionType()
            .fitSize(props.size, geoGraticule10())
            .translate(props.translate)      
        const path = d3.geoPath().projection(projection)

        //uses d3 to inject the data into the svg element
        const features = svg.selectAll(".country")
            .data(geoJson ? geoJson.features : [])
            .enter().append("path")

            //basic styling attributes
            .attr("d", path)
            .attr("fill", "none")
            .attr("stroke", "aliceblue")
            .attr("stroke-width", "0.5px")

            //allows pointer events anywhere inside the path even when fill=none
            .attr("pointer-events", "visibleFill")
            .attr("visibility", "visible")

            //sets the path element id to the continent name
            .attr("id", (d) => {
                 return `${d.properties.continent}`
            })

            //selects the current continent and highlights it by increasing the stroke width
            .on("mouseover", (d,i) => {
                svg.select(`#${i.properties.continent}`).attr("stroke-width", "2px")
            })

            //deselects
            .on("mouseleave", (d,i) => {
                svg.select(`#${i.properties.continent}`).attr("stroke-width", "0.5px")
            })

            //adds the .country attribute to allow for later updates on the svg element
            .attr("class", "country")
    }, [geoJson]);

    return (
        <div className="bg-blue-400">
            <svg ref={svgRef} viewBox={`0 0 ${props.size[0]} ${props.size[1]}`} />
        </div>
    )
}

export default TestMap

当我使用unsimplifed json文件时,它工作得很好。每个国家都被高亮显示,但是笔划宽度的重绘需要一段时间。当我所做的只是将WorldMapAtlas中的fetch更改为简化的json时,会出现一个轮廓(它似乎并不特定于一个路径,只有当所有路径元素都被删除时才会消失(dev工具)),并且无论光标在哪里,只有json中的最后一个特征被高亮显示。
红点是我的光标所在的位置。
我花了很多时间在这上面,我很感激我能得到的任何帮助!谢谢

jvidinwx

jvidinwx1#

在尝试了很多不同的简化选项之后,我觉得自己很傻。你所要做的就是在输出命令中添加gj 2008选项。

gj2008            [GeoJSON] use original GeoJSON spec (not RFC 7946)

这修复了所有的问题!虽然我不知道为什么,我不知道如何检查原始的GeoJSON规范,我也不知道有什么不同。希望这能帮助任何遇到同样问题的人!

相关问题