动态新维度与D3 JS并行集 [英] Dynamically new dimensions with D3 JS parallel sets
问题描述
您好,我想动态更改我的并行设置图表的尺寸。
http://www.jasondavies.com/parallel-sets/
var chart = d3.parsets()
.dimensions([Survived,Sex,Age,Class]);
var vis = d3.select(#vis)。append(svg)
.attr(width,chart.width())
.attr (height,chart.height());
d3.csv(titanic.csv,function(csv){
vis.datum(csv).call(chart);
});
我想动态更改生存,性别,年龄,
现在我现在是:
< form name =myform>
< label for =dimensions1>< input type =checkboxid =dimensions1
onClick =changedimensions()>生存,年龄,类< / label>< / form>
b $ b
函数
function changedimensions(){
var chart = d3。 parsets()
.dimensions([Survived,Age,Class])
.width(1300);
var vis = d3.select #vis)。append(svg)
.attr(width,chart.width())
.attr(height,chart.height());
d3.csv(data.csv,function(csv){
vis.datum(csv).call(chart);
});
问题是,这个方法只是生成一个全新的图表(有新的维度)在旧的图表下面:(
这里是没有复选框选中时首先加载的整个脚本:
var chart = d3.parsets()
.dimensions([Survived,Sex,Age,Class]);
var vis = d3.select(#vis)。append(svg)
.attr(width,chart.width())
.attr (height,chart.height());
var partition = d3.layout.partition()
.sort(null)
.size([chart.width(),chart.height()* 5/4 ]
.children(function(d){return d.children?d3.values(d.children):null;})
.value(function(d){return d.count;} );
var ice = false;
function curves(){
var t = vis.transition()。duration(500);
if(ice){
t.delay(1000);
icicle();
}
t.call(chart.tension(this.checked?.5:1));
}
d3.csv(titanic.csv,function(csv){
vis.datum(csv).call(chart);
window.icicle = function(){
var newIce = this.checked,
tension = chart.tension();
if(newIce === ice)return;
if(ice = newIce){
var dimensions = [];
vis.selectAll(g.dimension)
.each(function(d){dimensions.push(d) ;});
dimensions.sort(function(a,b){return ay - by;});
var root = d3.parsets.tree({children:{}},csv,dimensions .map(function(d){return d.name;}),function(){return 1;}),
nodes = partition(root),
nodesByPath = {};
node.forEach(function(d){
var path = d.data.name,
p = d;
while((p = p.parent)& p.data。 name){
path = p.data.name +\0+ path;
}
if(path)nodesByPath [path] = d;
}
var data = [];
vis.on(mousedown.icicle,stopClick,true)
.select(。ribbon)。selectAll(path)
.each(function(d){
var node = nodesByPath [d.path],
s = d.source,
t = d.target;
s.node.x0 = t.node.x0 = 0;
s.x0 = t.x0 = node.x;
s.dx0 = s.dx;
t.dx0 = t.dx;
s.dx = t.dx = node.dx;
data.push(d);
});
iceTransition(vis.selectAll(path))
.attr(d,function(d){
var s = d.source,
t = d.target ;
return ribbonPath(s,t,tension);
})
.style(stroke-opacity,1);
iceTransition(vis.selectAll(text.icicle)
.data(data)
.enter()。append(text)
.attr ,icicle)
.attr(text-anchor,middle)
.attr(dy,.3em)
.attr (d){
returntranslate(+ [d.source.x0 + d.source.dx / 2,d.source.dimension.y0 + d.target.dimension.y0>> 1] +)rotate(90);
})
.text(function(d){return d.source.dx> 15?d.node.name:null;})
.style(opacity,1e-6))
.style(opacity,1);
iceTransition(vis.selectAll(g.dimension rect,g.category)
.style(opacity,1))
.style(opacity,1e-6)
.each(end,function(){d3.select(this).attr(visibility,hidden);});
iceTransition(vis.selectAll(text.dimension))
.attr(transform,translate(0,-5));
vis.selectAll(tspan.sort)。style(visibility,hidden);
} else {
vis.on(mousedown.icicle,null)
.select(。ribbon)。selectAll(path)
.each (d){
var s = d.source,
t = d.target;
s.node.x0 = s.node.x;
s.x0 = sx;
s.dx = s.dx0;
t.node.x0 = t.node.x;
t.x0 = tx;
t.dx = t.dx0;
});
iceTransition(vis.selectAll(path))
.attr(d,function(d){
var s = d.source,
t = d.target ;
return ribbonPath(s,t,tension);
})
.style(stroke-opacity,null);
iceTransition(vis.selectAll(text.icicle))
.style(opacity,1e-6).remove
iceTransition(vis.selectAll(g.dimension rect,g.category)
.attr(visibility,null)
.style(opacity,1e-6))
.style(opacity,1);
iceTransition(vis.selectAll(text.dimension))
.attr(transform,translate(0,-25));
vis.selectAll(tspan.sort)。style(visibility,null);
}
};
d3.select(#icicle)
.on(change,icicle)
.each(icicle)
});
function iceTransition(g){
return g.transition()。duration(1000);
}
函数ribbonPath(s,t,张力){
var sx = s.node.x0 + s.x0,
tx = t.node。 x0 + t.x0,
sy = s.dimension.y0,
ty = t.dimension.y0;
return(tension === 1?[
M,[sx,sy],
L,[tx,ty],
h,t .dx,
L,[sx + s.dx,sy],
Z]
:[M,[sx,sy],
C,[sx,m0 =张力* sy +(1-张力)* ty],b $ b [tx,m1 =张力* ty + tx,ty],
h,t.dx,
C,[tx + t.dx,m1], ,[sx + s.dx,sy],
Z])join();
}
function stopClick(){d3.event.stopPropagation(); }
//给定一个文本函数和宽度函数,如果必要,截断文本
//适合给定的宽度。
function truncateText(text,width){
return function(d,i){
var t = this.textContent = text(d,i),
w = width , 一世);
if(this.getComputedTextLength()< w)return t;
this.textContent =...+ t;
var lo = 0,
hi = t.length + 1,
x;
while(lo< hi){
var mid = lo + hi> 1;
if((x = this.getSubStringLength(0,mid))< w)lo = mid + 1;
else hi = mid;
}
return lo> 1? t.substr(0,lo-2)+...:;
};
}
d3.select(#file)。on(change,function(){
var file = this.files [0],
reader = new FileReader;
reader.onloadend = function(){
var csv = d3.csv.parse(reader.result);
vis.datum(csv).call
.value(csv [0] .hasOwnProperty(Number)?function(d){return + d.Number;}:1)
.dimensions(function(d){return d3.keys (d [0])。filter(function(d){return d!==Number;})sort();}));
};
reader.readAsText ;
});
您的问题在这里:
var vis = d3.select(#vis)。append(svg)
pre>
这会附加一个新
< svg>
元素。因此,如果您在每次更改维度时都执行此操作,您将会获得另一个图表。
但是,您可以将此<$ c在您的
changedimensions
函数之外添加$ c> append ,并且简单地引用vis
更新图表:var vis = d3.select(#vis)append(svg)
// ...
function changedimensions(){
// ...
vis.call(chart);
}
我没有测试更新一个非常多的图表,让我知道您是否遇到任何进一步的问题。
Hi i'm trying to dynamically change the dimensions of my parallel set chart.
http://www.jasondavies.com/parallel-sets/
var chart = d3.parsets() .dimensions(["Survived", "Sex", "Age", "Class"]); var vis = d3.select("#vis").append("svg") .attr("width", chart.width()) .attr("height", chart.height()); d3.csv("titanic.csv", function(csv) { vis.datum(csv).call(chart); });
i want to dynamically change "Survived", "Sex", "Age", "Class" to "Survived, "Age", "Class" with a simple checkbox.
what i have now is:
<form name="myform"> <label for="dimensions1"><input type="checkbox" id="dimensions1" onClick="changedimensions()">Survived, Age, Class</label> </form>
the function
function changedimensions(){ var chart = d3.parsets() .dimensions(["Survived", "Age", "Class"]) .width(1300); var vis = d3.select("#vis").append("svg") .attr("width", chart.width()) .attr("height", chart.height()); d3.csv("data.csv", function(csv) { vis.datum(csv).call(chart); });
problem is that this method just generates a whole new chart (with the new dimensions) below the old one :(
here is the whole script that is first loaded without the checkbox checked:
var chart = d3.parsets() .dimensions(["Survived", "Sex", "Age", "Class"]); var vis = d3.select("#vis").append("svg") .attr("width", chart.width()) .attr("height", chart.height()); var partition = d3.layout.partition() .sort(null) .size([chart.width(), chart.height() * 5 / 4]) .children(function(d) { return d.children ? d3.values(d.children) : null; }) .value(function(d) { return d.count; }); var ice = false; function curves() { var t = vis.transition().duration(500); if (ice) { t.delay(1000); icicle(); } t.call(chart.tension(this.checked ? .5 : 1)); } d3.csv("titanic.csv", function(csv) { vis.datum(csv).call(chart); window.icicle = function() { var newIce = this.checked, tension = chart.tension(); if (newIce === ice) return; if (ice = newIce) { var dimensions = []; vis.selectAll("g.dimension") .each(function(d) { dimensions.push(d); }); dimensions.sort(function(a, b) { return a.y - b.y; }); var root = d3.parsets.tree({children: {}}, csv, dimensions.map(function(d) { return d.name; }), function() { return 1; }), nodes = partition(root), nodesByPath = {}; nodes.forEach(function(d) { var path = d.data.name, p = d; while ((p = p.parent) && p.data.name) { path = p.data.name + "\0" + path; } if (path) nodesByPath[path] = d; }); var data = []; vis.on("mousedown.icicle", stopClick, true) .select(".ribbon").selectAll("path") .each(function(d) { var node = nodesByPath[d.path], s = d.source, t = d.target; s.node.x0 = t.node.x0 = 0; s.x0 = t.x0 = node.x; s.dx0 = s.dx; t.dx0 = t.dx; s.dx = t.dx = node.dx; data.push(d); }); iceTransition(vis.selectAll("path")) .attr("d", function(d) { var s = d.source, t = d.target; return ribbonPath(s, t, tension); }) .style("stroke-opacity", 1); iceTransition(vis.selectAll("text.icicle") .data(data) .enter().append("text") .attr("class", "icicle") .attr("text-anchor", "middle") .attr("dy", ".3em") .attr("transform", function(d) { return "translate(" + [d.source.x0 + d.source.dx / 2, d.source.dimension.y0 + d.target.dimension.y0 >> 1] + ")rotate(90)"; }) .text(function(d) { return d.source.dx > 15 ? d.node.name : null; }) .style("opacity", 1e-6)) .style("opacity", 1); iceTransition(vis.selectAll("g.dimension rect, g.category") .style("opacity", 1)) .style("opacity", 1e-6) .each("end", function() { d3.select(this).attr("visibility", "hidden"); }); iceTransition(vis.selectAll("text.dimension")) .attr("transform", "translate(0,-5)"); vis.selectAll("tspan.sort").style("visibility", "hidden"); } else { vis.on("mousedown.icicle", null) .select(".ribbon").selectAll("path") .each(function(d) { var s = d.source, t = d.target; s.node.x0 = s.node.x; s.x0 = s.x; s.dx = s.dx0; t.node.x0 = t.node.x; t.x0 = t.x; t.dx = t.dx0; }); iceTransition(vis.selectAll("path")) .attr("d", function(d) { var s = d.source, t = d.target; return ribbonPath(s, t, tension); }) .style("stroke-opacity", null); iceTransition(vis.selectAll("text.icicle")) .style("opacity", 1e-6).remove(); iceTransition(vis.selectAll("g.dimension rect, g.category") .attr("visibility", null) .style("opacity", 1e-6)) .style("opacity", 1); iceTransition(vis.selectAll("text.dimension")) .attr("transform", "translate(0,-25)"); vis.selectAll("tspan.sort").style("visibility", null); } }; d3.select("#icicle") .on("change", icicle) .each(icicle); }); function iceTransition(g) { return g.transition().duration(1000); } function ribbonPath(s, t, tension) { var sx = s.node.x0 + s.x0, tx = t.node.x0 + t.x0, sy = s.dimension.y0, ty = t.dimension.y0; return (tension === 1 ? [ "M", [sx, sy], "L", [tx, ty], "h", t.dx, "L", [sx + s.dx, sy], "Z"] : ["M", [sx, sy], "C", [sx, m0 = tension * sy + (1 - tension) * ty], " ", [tx, m1 = tension * ty + (1 - tension) * sy], " ", [tx, ty], "h", t.dx, "C", [tx + t.dx, m1], " ", [sx + s.dx, m0], " ", [sx + s.dx, sy], "Z"]).join(""); } function stopClick() { d3.event.stopPropagation(); } // Given a text function and width function, truncates the text if necessary to // fit within the given width. function truncateText(text, width) { return function(d, i) { var t = this.textContent = text(d, i), w = width(d, i); if (this.getComputedTextLength() < w) return t; this.textContent = "…" + t; var lo = 0, hi = t.length + 1, x; while (lo < hi) { var mid = lo + hi >> 1; if ((x = this.getSubStringLength(0, mid)) < w) lo = mid + 1; else hi = mid; } return lo > 1 ? t.substr(0, lo - 2) + "…" : ""; }; } d3.select("#file").on("change", function() { var file = this.files[0], reader = new FileReader; reader.onloadend = function() { var csv = d3.csv.parse(reader.result); vis.datum(csv).call(chart .value(csv[0].hasOwnProperty("Number") ? function(d) { return +d.Number; } : 1) .dimensions(function(d) { return d3.keys(d[0]).filter(function(d) { return d !== "Number"; }).sort(); })); }; reader.readAsText(file); });
解决方案Your problem is here:
var vis = d3.select("#vis").append("svg")
This appends a new
<svg>
element. So if you do this every time you change a dimension, you'll get another chart.Instead, you can move this
append
outside of yourchangedimensions
function, and simply reference thevis
variable when updating the chart:var vis = d3.select("#vis").append("svg") // … function changedimensions() { // … vis.call(chart); }
I haven't tested updating a chart in-place very much, but do let me know if you encounter any further issues.
这篇关于动态新维度与D3 JS并行集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!