1

こんにちは、パラレル セット チャートのディメンションを動的に変更しようとしています。

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="checkbox" id="dimensions1" 
onClick="changedimensions()">Survived, Age, Class</label> </form>

関数

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 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);
});
4

1 に答える 1

1

あなたの問題はここにあります:

var vis = d3.select("#vis").append("svg")

これにより、新しい <svg>要素が追加されます。したがって、ディメンションを変更するたびにこれを行うと、別のグラフが表示されます。

代わりに、これを関数appendの外に移動し、グラフを更新するときに変数を参照するだけです。changedimensionsvis

var vis = d3.select("#vis").append("svg")
// …

function changedimensions() {
  // …
  vis.call(chart);
}

チャートをインプレースで更新することはあまりテストしていませんが、さらに問題が発生した場合はお知らせください。

于 2012-05-10T13:48:35.213 に答える