如何在 d3.js 中正确过渡堆积条
How to correctly transition stacked bars in d3.js
我正在尝试让堆叠条形图在条形来来去去时正确设置动画。某处可能有一个很好的例子(也许我会作为一个单独的问题来问),但我发现的例子没有显示单个堆栈元素退出和进入的转换我想确保随着条形图的退出,他们向下拖动上方的栏杆,当他们进入时,他们向上推上方的栏杆。我不希望在过渡过程中出现任何间隙或重叠。
任何人都可以指出一个执行此操作的示例吗?
纠正我的错误问题:
Ashitaka 用一个有用的 jsfiddle 回答了这个问题。他的回答促使我更仔细地查看 d3 stack layout,在那里我读到:
In the simplest case, layers is a two-dimensional array of values. All of the 2nd-dimensional arrays must be the same length.
所以,我得出结论,我的做法全错了。我根本不应该尝试删除堆栈栏。如果我的数据中的条形图要消失,我应该将它们保留在数据中并将它们的高度更改为零。这样过渡效果很好。我还没有处理新出现的柱状图。
转换堆叠图表(以及通常使用 SVG)的一个令人困惑的方面是坐标系原点位于左上角,这意味着 y 向下增加。
首先,我们的数据应该有2个相关的属性:
y
, bar的高度
和 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); };
接下来,我们创建一个 key function 以便元素绑定到正确的数据很关键:
var joinKey = function (d) { return d.name; };
如果没有此功能,D3 将使用其索引连接数据,这会破坏一切。
现在,要从堆栈中删除或添加一组柱状图,我们执行以下步骤:
重新计算堆栈:
var newStack = stack(enabledSeries());
使用 data function:
将新堆栈与当前选择的图层合并
layers = layers.data(newStack, joinKey);
使用我们的键函数,D3 确定要添加、删除或更新的柱。
访问相应的栏:
layers.enter()
包含 "enter selection",即要添加的新柱组。
layers.exit()
包含 "exit selection",即要删除的柱线集。
并且简单地 layers
包含 "update selection",即要更新的柱。然而,after enter.append the "update selection" is modified to contain both entering and updating elements。不过这在 D3 v4 中有所改变。
为条形图设置动画:
对于添加的柱,我们使用 height
0 和 y
位置 barBaseY
创建它们。
然后我们为所有条形图的 height
和 y
属性设置动画。
对于删除的条,我们将它们设置为 height
0 和 y
位置 barBaseY
的动画,这与添加条完全相反。然后我们为所有剩余条形图的 height
和 y
属性设置动画。 D3 足够聪明,可以同时渲染所有这些动画。
这里是a pared down version of the stacked chart I linked to in my first comment。
我正在尝试让堆叠条形图在条形来来去去时正确设置动画。某处可能有一个很好的例子(也许我会作为一个单独的问题来问),但我发现的例子没有显示单个堆栈元素退出和进入的转换我想确保随着条形图的退出,他们向下拖动上方的栏杆,当他们进入时,他们向上推上方的栏杆。我不希望在过渡过程中出现任何间隙或重叠。
任何人都可以指出一个执行此操作的示例吗?
纠正我的错误问题: Ashitaka 用一个有用的 jsfiddle 回答了这个问题。他的回答促使我更仔细地查看 d3 stack layout,在那里我读到:
In the simplest case, layers is a two-dimensional array of values. All of the 2nd-dimensional arrays must be the same length.
所以,我得出结论,我的做法全错了。我根本不应该尝试删除堆栈栏。如果我的数据中的条形图要消失,我应该将它们保留在数据中并将它们的高度更改为零。这样过渡效果很好。我还没有处理新出现的柱状图。
转换堆叠图表(以及通常使用 SVG)的一个令人困惑的方面是坐标系原点位于左上角,这意味着 y 向下增加。
首先,我们的数据应该有2个相关的属性:
y
, bar的高度和
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); };
接下来,我们创建一个 key function 以便元素绑定到正确的数据很关键:
var joinKey = function (d) { return d.name; };
如果没有此功能,D3 将使用其索引连接数据,这会破坏一切。
现在,要从堆栈中删除或添加一组柱状图,我们执行以下步骤:
重新计算堆栈:
var newStack = stack(enabledSeries());
使用 data function:
将新堆栈与当前选择的图层合并layers = layers.data(newStack, joinKey);
使用我们的键函数,D3 确定要添加、删除或更新的柱。
访问相应的栏:
layers.enter()
包含 "enter selection",即要添加的新柱组。layers.exit()
包含 "exit selection",即要删除的柱线集。并且简单地
layers
包含 "update selection",即要更新的柱。然而,after enter.append the "update selection" is modified to contain both entering and updating elements。不过这在 D3 v4 中有所改变。
为条形图设置动画:
对于添加的柱,我们使用
height
0 和y
位置barBaseY
创建它们。 然后我们为所有条形图的height
和y
属性设置动画。对于删除的条,我们将它们设置为
height
0 和y
位置barBaseY
的动画,这与添加条完全相反。然后我们为所有剩余条形图的height
和y
属性设置动画。 D3 足够聪明,可以同时渲染所有这些动画。
这里是a pared down version of the stacked chart I linked to in my first comment。