d3.js 加快React中D3散点图的缩放速度

gwo2fgha  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(235)

我想用支持鼠标滚动缩放的D3制作大约100.000个项目的散点图。我设法在React中实现了这一点。不幸的是,缩放交互非常慢。有没有办法让缩放更平滑和即时?
我的useEffect如下所示

useEffect(() => {
        //setting up container width and height
        const w = width;
        const h = height;

        // create the result chart
        const resultChart = d3.select(resultChartRef.current)
            .attr('width', w)
            .attr('height', h)
            .style('margin-top', '10px');

        // Create the latent chart
        const latentChart = d3.select(latentChartRef.current)
            .attr('width', w)
            .attr('height', h)
            .style('margin-top', '10px');

            // d3.select(resultChartRef.current).selectAll().remove().exit()

        // Compute the scales of the two charts
        const resultScales = setScalesChart(dimRedData?.data?.result, w, h)
        const latentScales = setScalesChart(dimRedData?.data?.latent_space, w, h)

        if (currentZoomState) {
            const newXScale = currentZoomState.rescaleX(resultScales[0])
            const newYScale = currentZoomState.rescaleX(resultScales[1])
            resultScales[0].domain(newXScale.domain())
            resultScales[1].domain(newYScale.domain())
        };

        const xAxis = d3.axisBottom(resultScales[0]).ticks(10)
        const yAxis = d3.axisLeft(resultScales[0]).ticks(10)

        const gX = resultChart.append('g').call(xAxis).attr('transform', `translate(0, ${h})`);
        const gY = resultChart.append('g').call(yAxis);

        // TODO: styling properties http://www.d3noob.org/2014/02/styles-in-d3js.html
        resultChart.selectAll('*').remove();
        resultChart.selectAll('circle')
            // select dataset
            .data(filterData(dimRedData?.data?.result))
            .enter()
            // Assign data value
            .append('circle')
                .attr('cx', d => resultScales[0](d[0]))
                .attr('cy', d => resultScales[1](d[1]))
                .attr('r', 2)
            // Add item colour
            .style("fill", function(d, i) {
                return dimRedData.data.colour[0][i]
            })
            // Set border width
            .style("stroke-width", 0.5)
            // Add border colour
            .style("stroke", "black");

        latentChart.selectAll()
            // select dataset
            .data(filterData(dimRedData?.data?.latent_space))
            .enter()
            // Assign data value
            .append('circle')
                .attr('cx', d => latentScales[0](d[0]))
                .attr('cy', d => latentScales[1](d[1]))
                .attr('r', 2)
            // Add item colour
            .style("fill", function(d, i) {
                return dimRedData.data.colour[0][i]
            })
            // Set border width
            .style("stroke-width", 0.5)
            // Add border colour
            .style("stroke", "black");

        // Zoom of the chart
        const zoomBehavior = d3.zoom()
            .extent([[0, 0],[w, h]])
            .scaleExtent([0.5, 5])
            .translateExtent([[0,0], [w, h]])
            .on("zoom", (e) => {
                const zoomState = d3.zoomTransform(resultChart.node())
                setCurrentZoomState(zoomState);
                console.log("ZOOM!")
            });

        // Add zoom functionality to the result chart
        resultChart.call(zoomBehavior)

    }, [random, projectionFullScreen, currentZoomState]);

我想知道是否有可能加快速度,或者我应该换一种不同的方法。甚至可能是一种与D3不同的技术。

rkttyhzu

rkttyhzu1#

可能的事情:
不是ReactMaven,但是缩放是否每次都调用useEffect函数呢?如果是这样,那就不好了,因为它至少要从零开始销毁和重新添加resultChart的所有100,000个对象。您可以将它们全部删除(resultChart.selectAll('*').remove();),然后通过enter()再次将它们全部添加进去。在D3方面,您应该只删除(通过exit())没有相应数据的现有对象,添加(通过enter())数据没有相应对象的对象,并更新数据和对象都存在的对象。要实现这一点,您需要一个关键函数作为.data(filterData(dimRedData?.data?.latent_space))调用的第二个参数,通常它引用数据对象的ID字段。
其次,即使这样做了,这是一个svg,这100,000个圆圈被添加到,所以它会很慢,因为通过缩放svg放大和缩小涉及浏览器重新绘制它包含的所有这100,000个对象(它可能有一些智能,而不是“绘制”那些在放大视图之外,但它仍然必须计算)
我以前做过一个基于d3的散点图,上面有很多点,我在缩放/平移时唯一的方法就是把这些点绘制到画布图像上,然后放大和缩小。但是这意味着你的圆看起来会有锯齿/模糊,这取决于抗锯齿。因此,如果您继续使用这条路线,可能需要切换到正方形“点”。我还需要编写自己的代码来与点进行交互
我想总结一下,除非这是为了你自己的教育或者你受到其他问题的限制,否则去谷歌一下react散点图库,看看是否有人已经解决了这个问题;- )

相关问题