动态新维度与D3 JS并行集 [英] Dynamically new dimensions with D3 JS parallel sets

查看:165
本文介绍了动态新维度与D3 JS并行集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我想动态更改我的并行设置图表的尺寸。



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 your changedimensions function, and simply reference the vis 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屋!

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