如何正确过渡d3.js中的堆叠条形图 [英] How to correctly transition stacked bars in d3.js

查看:339
本文介绍了如何正确过渡d3.js中的堆叠条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取堆积的条形图,以随着条形图的来回正确地设置动画.可能在某个地方有一个很好的例子(也许我会作为一个单独的问题来问),但是我发现的例子没有显示退出和进入各个堆栈元素的过渡,我想确保随着酒吧的退出,他们将其上方的条形图向下拖动,并在进入时将其上方的条形图向上推.而且我不希望过渡期间出现任何差距或重叠.

有人能指出我的例子吗?


更正我的问题: Ashitaka用一个有用的jsfiddle回答了这个问题.他的回答促使我更仔细地研究 d3堆栈布局,其中我读到:

在最简单的情况下,图层是值的二维数组.所有第二维数组的长度必须相同.

因此,我得出的结论是我要解决所有这些错误.我根本不应该尝试删除堆栈栏.如果数据中的条形消失,则应将其保留在数据中并将其高度更改为零.这样,过渡效果很好.我还不必处理出现的新酒吧.

解决方案

转换堆积图(通常与SVG一起使用)的一个令人困惑的方面是坐标系原点位于左上角,这意味着y向下增加.

首先,我们的数据应具有2 y个相关属性:

  • y,条的高度

  • y0,即条形图在其他条形图上方的基线或y位置.这应该由d3.layout.stack()计算.

然后,我们应该创建2个音阶:

  • 一个高度,完全符合预期:

    var heightScale = d3.scale.linear()
      .domain([0, maxStackY])
      .range([0, height]);
    

  • 其中一个用于y位置,其作用相反:

    var yScale = d3.scale.linear()
      .domain([0, maxStackY])
      .range([height, 0]);
    

使用这两个比例尺,我们可以创建一些函数来计算条形的适当y位置和高度:

var barBaseY = function (d) { return yScale(d.y0); };

var barTopY = function (d) { return yScale(d.y0 + d.y); };

var barHeight = function (d) { return heightScale(d.y); };

接下来,至关重要的是,我们创建一个键函数,以便使元素绑定到正确的数据:

var joinKey = function (d) { return d.name; };

如果没有此功能,D3将使用其索引连接数据,这将破坏所有内容.

现在,要从堆栈中删除或添加一组柱,我们执行以下步骤:

  1. 重新计算堆栈:

    var newStack = stack(enabledSeries());
    

  2. 使用数据函数将当前选择的图层加入新堆栈:

    layers = layers.data(newStack, joinKey);
    

    借助我们的键功能,D3可以确定要添加,删除或更新的小节.

  3. 访问相应的栏:

    • layers.enter()包含输入选择",即要添加的一组新的条.

    • layers.exit()包含退出选择",即要删除的一组条形.

    • layers仅包含更新选择",即要更新的条.但是,在enter.append之后添加修改更新选择"以包含输入和更新元素.不过,在D3 v4中,这种情况已经改变.

  4. 使条形动起来:

    • 对于添加的条,我们使用height 0和y位置barBaseY创建它们. 然后,为所有钢筋的heighty属性设置动画.

    • 对于已删除的条,我们将它们设置为height 0和y位置barBaseY的动画,这与添加条完全相反.然后,为其余所有条的heighty属性设置动画. D3足够聪明,可以同时渲染所有这些动画.

这是我在第一条评论中链接到的堆叠图表的精简版本./p>

这是为什么必须同时将yheight属性设置为动画的直观解释.模拟尺寸下降"的条形.

I'm trying to get a stacked bar chart to animate correctly as bars come and go. There's probably a good example of this somewhere (maybe I'll ask as a separate question), but the examples I'm finding don't show transitions with individual stack elements exiting and entering I want to make sure that as bars are exiting, they drag down the bars above them, and as they're entering, they push up the bars above them. And I don't want any gaps or overlaps midway through the transition.

Can anyone point me to an example that does this?


Correcting my wrong-headed question: Ashitaka answered the question with a helpful jsfiddle. His answer prompted me to look at the d3 stack layout more closely, where I read:

In the simplest case, layers is a two-dimensional array of values. All of the 2nd-dimensional arrays must be the same length.

So, I concluded I was going about this all wrong. I shouldn't have been trying to remove stack bars at all. If bars in my data were going to disappear, I should leave them in the data and change their height to zero. That way the transitions work great. I haven't yet had to deal with new bars appearing.

解决方案

One confusing aspect of transitioning stacked charts (and working with SVG in general) is that the coordinate system origin is at the top-left corner, which means that y increases downwards.

First, our data should have 2 y related attributes:

  • y, the height of the bar

  • And y0, the baseline or the y position of the bar when it's on top of other bars. This should be calculated by d3.layout.stack().

Then, we should create 2 scales:

  • One for height, which works exactly as expected:

    var heightScale = d3.scale.linear()
      .domain([0, maxStackY])
      .range([0, height]);
    

  • And one for the y position, which works in the reverse way:

    var yScale = d3.scale.linear()
      .domain([0, maxStackY])
      .range([height, 0]);
    

With these two scales, we can create some functions to calculate the appropriate y positions and heights of our bars:

var barBaseY = function (d) { return yScale(d.y0); };

var barTopY = function (d) { return yScale(d.y0 + d.y); };

var barHeight = function (d) { return heightScale(d.y); };

Next, it's critical that we create a key function so that elements are bound to the correct data:

var joinKey = function (d) { return d.name; };

Without this function D3 would join the data using its index, which would break everything.

Now, to remove or add a set of bars from the stack, we take these steps:

  1. Recalculate the stack:

    var newStack = stack(enabledSeries());
    

  2. Join the new stack with the current selection of layers with the data function:

    layers = layers.data(newStack, joinKey);
    

    With our key function, D3 determines the bars that are to be added, removed or updated.

  3. Access the appropriate bars:

  4. Animate the bars:

    • For added bars, we create them with height 0 and y position barBaseY. Then we animate all the bars' height and y attributes.

    • For removed bars, we animate them to height 0 and y position barBaseY, the exact opposite of adding bars. Then we animate all the remaining bars' height and y attributes. D3 is smart enough to render all these animations at the same time.

Here's a pared down version of the stacked chart I linked to in my first comment.

And here's a visual explanation of why you have to animate both y and height attributes to simulate a bar diminishing in size "going down".

这篇关于如何正确过渡d3.js中的堆叠条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆