平移/缩放后渲染Leaflet画布

3
我正在尝试使用d3和React的路径生成器在Leaflet上显示geoJSON数据。通过以下代码,我能够生成与地图正确匹配的路径,请参见附图。

working display

一切都很好!但是,我一旦在Leaflet中平移或缩放,图形就会消失...canvas html元素仍然存在,并且甚至正确地转换到其新位置,但不再有图形。
实际上,它只在平移完成后出现。因此,只要我没有释放鼠标点击,图形就在这里,甚至沿着地图正确移动。但最终当平移完成时,它就消失了。
对此有任何想法吗?:)
感谢您的帮助。
美国数据:https://bost.ocks.org/mike/leaflet/us-states.json
import React, { useEffect, useState } from 'react'
import 'leaflet/dist/leaflet.css'
import * as d3 from 'd3'
var L = null

const source = require('./data/states-us.geojson')


const AppCanvas = () => {
    const [mapElement, setMap] = useState(null)

    useEffect(() => {
        L = require('leaflet')
        // Map creation
        if (!mapElement) {
            const origin = [37.8, -96.9]
            const initialZoom = 4

            const map = L.map('map')
                .setView(origin, initialZoom)
                .addLayer(
                    new L.TileLayer(
                        'http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png'
                    )
                )

            map.whenReady(() => {
                // Create canvas element to the correct size
                L.canvas().addTo(map)
                const canvas = d3.select('#map').select('canvas')

                const projection = d3.geoTransform({
                    point: function (x, y) {
                        const point = map.latLngToLayerPoint(new L.LatLng(y, x))
                        this.stream.point(point.x, point.y) // this : NO ARROW FUNCTION
                    },
                })
                const context = canvas.node().getContext('2d')

                // Path generator
                const path = d3
                    .geoPath()
                    .projection(projection)
                    .context(context)

                d3.json(source).then((data) => {
                    context.beginPath()
                    path(data)
                    context.stroke()
                })

                setMap(map)
            })
        }
    })

    return (
        <div>
            <div
                style={{
                    position: 'absolute',
                    top: 0,
                    bottom: 0,
                    left: 0,
                    right: 0,
                    zIndex: 0,
                }}
                id="map"
            ></div>
        </div>
    )
}

画布跟随地图,在每次平移/缩放结束后重新渲染。

1个回答

2
我找到了一个解决方案:每当Leaflet画布图层上的“update”事件被触发时,重新渲染路径。
const canvasLayer = L.canvas().addTo(map)

canvasLayer.on('update', (e) => {
    context.save()
    context.clearRect(
        0,
        0,
        map.getSize().x,
        map.getSize().y
    )
    context.beginPath()
    path(data)
    context.stroke()
    context.restore()
})

也许这并不是最优的解决方案,但至少在视觉上效果很好。画布总是渲染并始终正确地定位在地图上。你可以在互联网上找到一些例子,其中画布只是在地图“缩放”事件之后再次渲染,导致用户看到画布被删除/添加的情况。但这里不是这种情况。
我已经测试了一个包含350个多边形/5000个点的画布,没有性能问题,一切都很流畅。 Canvas layer example

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接