圆包装图 - 两组值之间的转换 [英] Circle-packing diagram - transition between two set of values
问题描述
我有一个非常类似于。
这里是处理平滑圆包转换的整个代码(除了数据定义和按钮创建):
var diameter = 500,
format = d3.format(,d),
dataSource = 2;
var pack = d3.layout.pack()
.size([diameter - 4,diameter - 4])
.value(function(d){return d.size;}) ;
var svg = d3.select(body)。append(svg)
.attr(width,diameter)
.attr(height,diameter);
var data = getData();
var vis = svg.datum(data).selectAll(。node)
.data(pack.nodes)
.enter (G);
var titles = vis.append(title)
.attr(x,function(d){return dx;})
.attr(y ,function(d){return dy;})
.text(function(d){return d.name +
(d.children?::+ format(d.value) );});
var circles = vis.append(circle)
.attr(stroke,black)
.style(fill,function returnd.children?tan:beige;})
.attr(cx,function(d){return dx;})
.attr d){return dy;})
.attr(r,function(d){return dr;});
updateVis();
function updateVis(){
if(dataSource == 0)
pack.value(function(d){return d.size;});
if(dataSource == 1)
pack.value(function(d){return 100;});
if(dataSource == 2)
pack.value(function(d){return 1 +
Math.floor(Math.random()* 301);});
var data1 = pack.nodes(data);
titles.attr(x,function(d){return dx;})
.attr(y,function(d){return dy;})
.text(function(d){return d.name +
(d.children?::+ format(d.value));});
circle.transition()
.duration(5000)
.attr(cx,function(d){return dx;})
.attr cy,function(d){return dy;})
.attr(r,function(d){return dr;});
};
I have a diagram very similar to circle packing
At some point, a user wants to see some different data. Obviously, a different diagram can be displayed immediately, but transition would be much better from perception and cognition point of view. NOTE: The hierarchical structure remains the same, there is no new or deleted nodes, just underlying values that determine circle size change.
What would be the good way to implement such smooth transition between two circle pack graphs of the same structure but different values?
(Of course, during transition, that lets say lasts 10 sec, there is no need to keep relation between circles like in original graph, circles can intersect and pass one over another)
I know there is similar solution for treemaps. However, it can't be applied on circle packing at all. Treemaps even have a special function sticky() that helps in such cases.
EDIT: I am attaching new version of jsfiddle.
Some functionality now started working. Transitions driven with random data are beautiful.
I have two concerns at this moment:
- I don't know how to update tooltips. This is important, user should be able to identify data points via tooltips. On teh other hand, good thing is they don't need to be interpolated during transition, abrupt change is sufficient, but I don't know how to do it.
- I really don't understand the code. Coding was mostly trial/error process. I would appreciate if somebody verifies the code is good, or maybe not good, or it could be different.
EDIT 2: I resolved problems, and attached jsfiddle in the answer if somebody needs the code. Everybody is still welcome to comment on solution.
Most critical part of the code, it seems is:
function updateVis() {
// change pack value
if (updateMethod == 0)
pack.value(function(d) { return d.size; });
if (updateMethod == 1)
pack.value(function(d) { return 100; });
if (updateMethod == 2)
pack.value(function(d) { return 1 + Math.floor(Math.random()*101); });
var data1 = pack.nodes(data);
// titles = ?????
circles.transition()
.duration(2000)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; });
return;
};
Thanks in advance for any help or hint.
It looks that I finally resolved all issues. jsfiddle is here.
Here is the whole code (except data definition and button creation) that handles smooth circle pack layout transition:
var diameter = 500,
format = d3.format(",d"),
dataSource = 2;
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter);
var data = getData();
var vis = svg.datum(data).selectAll(".node")
.data(pack.nodes)
.enter()
.append("g");
var titles = vis.append("title")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.text(function(d) { return d.name +
(d.children ? "" : ": " + format(d.value)); });
var circles = vis.append("circle")
.attr("stroke", "black")
.style("fill", function(d) { return !d.children ? "tan" : "beige"; })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; });
updateVis();
function updateVis() {
if (dataSource == 0)
pack.value(function(d) { return d.size; });
if (dataSource == 1)
pack.value(function(d) { return 100; });
if (dataSource == 2)
pack.value(function(d) { return 1 +
Math.floor(Math.random()*301); });
var data1 = pack.nodes(data);
titles.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.text(function(d) { return d.name +
(d.children ? "" : ": " + format(d.value)); });
circles.transition()
.duration(5000)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; });
};
这篇关于圆包装图 - 两组值之间的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!