javascript - 散点图更新 : same number of data points, 但有新的数据点

标签 javascript reactjs d3.js

提前道歉,我的问题不包含代码,而是关于 D3 以及如何正确构建我的应用程序的高级问题。我将尝试使我的问题尽可能清晰和简洁:

我正在构建一个 React/D3 应用程序,该应用程序创建 NBA 球队 Logo 的散点图,允许用户单击按钮来选择 X 和 Y 轴的变量。用户还可以过滤图表以仅包含某些球队(NBA 特定部门的球队)。

这是该应用程序的快速演示 gif,其中包含我遇到的主要问题:

enter image description here .

。 。 。 和 here这是我的应用程序的链接,供任何感兴趣的人使用。

什么工作正常

当我更改 X 或 Y 轴按钮(gif 的第二半)时,团队 Logo 会正确滑动到新位置。

什么地方工作不正常

当我更改分区(gif 的第一半)时,它会更改显示的 5 个团队 Logo ,这是正确的。然而,动画(我在 gif 中多次展示过)是不正确的。旧 Logo 应该简单地消失在适当的位置,而新 Logo 应该简单地出现在适当的位置。相反, Logo 会发生变化和滑动。

我明白为什么动画要这样做 - D3 在更新前看到 5 个数据点,在更新后看到 5 个数据点,但没有区分我的点是唯一的(不同的团队 Logo )。由于更新的数据点具有新的 (x,y) 位置(每个团队的统计数据不同),因此它只是将旧 Logo 动画到新 Logo 的位置。

我建议的修复

我认为我的应用程序的结构阻碍了解决这个问题。目前,我有一个容器组件,用于加载数据、过滤团队(基于所选的部门),然后将过滤后的数据(具有团队统计数据的对象数组)传递到创建 Logo 散点图的图形组件中。

另一方面,如果我将(所有 30 个团队的)完整对象传递给图形组件,那么我可以通过简单地让 D3 更改对象的“填充”来解决这个问题吗?标记被过滤掉后变为透明?这样,尽管 25 个是不可见的,但始终会绘制 30 个 Logo ,并且显示的 Logo 应能正确显示动画。

预先感谢您的想法!

编辑:如果帖子有任何不清楚的地方,请告诉我,我会尽力澄清。我尽量避免在没有代码的情况下发布问题,但这是一个相当高水平的问题,重点关注 D3 通用更新模式如何工作,以及如何构建具有在通用更新模式框架内工作的特定动画的图形。

Edit2:单选按钮内置于此处的容器组件中。使用我的 API 从数据库中获取数据,然后使用这些单选按钮来过滤数据,所有这些都是在容器组件中完成的。我正在考虑将这些单选按钮引入图形组件并使用 D3 构建它们。我想我可能不得不这么做。

Edit3:应该早点分享,这里是制作这些标记的 D3 代码:

const update = svg.select('g.points')
    .selectAll("rect")
    .data(graphData);

// Second exit and remove
update.exit().remove();

// Third Update
update
    .enter()
    .append("rect")
        .attr("transform", d => `translate(${(xScale(+d[xColname]) - logoRadius)}, ${(yScale(+d[yColname]) - logoRadius)})`)
        .attr("x", 0).attr("y", 0)
        .attr("height", logoRadius)
        .attr("width", logoRadius)
        .attr("fill", d => `url(#teamlogo-${d.teamAbbrev})`)
        .attr("opacity", 0.95);

// And Fourth transition
update
    .transition()
    .duration(750)
    .delay((d, i) => i * 15)
        .attr("transform", d => `translate(${(xScale(+d[xColname]) - logoRadius)}, ${(yScale(+d[yColname]) - logoRadius)})`)
        .attr("x", 0).attr("y", 0)
        .attr("height", logoRadius)
        .attr("width", logoRadius)
        .attr("fill", d => `url(#teamlogo-${d.teamAbbrev})`)
        .attr("opacity", 0.95);

最佳答案

这里的问题似乎只是在数据连接过程中缺少一个关键功能。

您在 comments section 中询问:

Doesn't the D3 general update pattern just look for the number of objects in the data array?

如果您设置了关键功能,答案是。问题是……

If a key function is not specified, then the first datum in data is assigned to the first selected element, the second datum to the second selected element, and so on. A key function may be specified to control which datum is assigned to which element, replacing the default join-by-index, by computing a string identifier for each datum and element. (source)

因此,如果您没有设置关键功能,因为您始终只有 5 个团队,那么当您更改分区时,您将无法有效地进行进入和退出选择,而只是更新一个:因为您按顺序绑定(bind)数据,D3 认为芝加哥公牛队和亚特兰大老鹰队是同一支球队。

解决办法:设置一个按键功能。

它可以很简单,就像使用团队缩写(假设它们是唯一):

const update = svg.select('g.points')
    .selectAll("rect")
    .data(graphData, function(d){
        return d.teamAbbrv;
    });

PS:只是一个与您的问题无关的问题:为什么要在此处附加矩形?既然您有 logoRadius,添加圆圈不是看起来更自然吗?最重要的是,数据表示将更加准确,因为无论其大小如何,圆的中心都位于正确的基准坐标处。矩形的情况并非如此,其中坐标 (x, y) 代表其左上角。

关于javascript - 散点图更新 : same number of data points, 但有新的数据点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51352540/

相关文章:

javascript - jQuery - 替换用户消息 - 重复自己

javascript - 使用 Cloud Code 验证自动续订订阅收据并更新 Parse

javascript - index.js 文件如何在 React 组件目录中工作?

reactjs - 将D3与Electron React应用程序结合使用

javascript - 在 D3 中用线连接矩形

c# - javascript按键按下问题

javascript - Angular 应用程序在 github.io 上抛出 404 错误

reactjs - 来自 material-ui 的 DataTables 分页不起作用

reactjs - 如何 : onClick/onChange for a <select>'s <option> in a child component

r - 如何在我的 R Shiny 应用程序中显示使用 rcharts 创建的图表?