在React中加速D3散点图的缩放



我想使用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不同的技术。

可能的事情:

不是react专家,但是缩放每次都调用useEffect函数吗?如果是这样,那就不好了,因为它至少要从头销毁并读取resultChart的所有100,000个对象。将它们全部删除(resultChart.selectAll('*').remove();),然后通过enter()再次将它们全部添加进来。在3d方面,您应该删除(通过exit())没有相应数据的现有对象,添加(通过enter())数据没有相应对象的对象,并更新数据和对象都存在的对象。为此,您需要一个键函数作为.data(filterData(dimRedData?.data?.latent_space))调用的第二个参数,通常它引用数据对象的id字段。

其次,即使这样做了,这是一个svg这10万个圆圈会被添加进去,所以它会很慢因为通过缩放svg来放大和缩小涉及到浏览器重新绘制它包含的所有10万个对象(它可能有一些智能而不是绘制在放大视图之外的对象但它仍然需要计算)

我之前做了一个基于3d的散点图,上面有很多点,我在放大/平移时获得性能的唯一方法是将点绘制到画布图像上,然后放大和缩小。但这意味着你的圆圈看起来参差不齐/模糊取决于抗锯齿,所以你可能需要切换到方形"点",如果你走这条路。我还需要编写自己的代码来与点

交互。我想总结一下,除非这是为了你自己的教育或你受其他问题的限制,去谷歌一个react散点图库,看看是否有人已经解决了这个问题;-)

最新更新