3

d3を使用して積み上げ棒グラフを作成しています。

この前の質問のおかげで、parentNode .__data__。keyを使用して親ノードに関連付けられたデータを子ノードにバインドしています。

データは、バーごとに1つのオブジェクトを持つ配列です(たとえば、「いいね」)。次に、各オブジェクトには、バーごとに個々の長方形を駆動する値の配列が含まれています。

data =  [{
          key = 'likes', values = [
            {key = 'blue-frog', value = 1}, 
            {key = 'goodbye', value = 2}
          ]
        }, {
          key = 'dislikes, values = [
            {key = 'blue-frog', value = 3},
            {key = 'goodbye', value = 4}
          ]
        }]

グラフは正常に機能しているため、親メトリックデータを子svg属性にバインドしています。

// Create canvas
bars = svg.append("g");

// Create individual bars, and append data
// 'likes' are bound to first bar, 'dislikes' to second
bar = bars.selectAll(".bar")
        .data(data)        
        .enter()
        .append("g");

// Create rectangles per bar, and append data
// 'blue-frog' is bound to first rectangle, etc.
rect = bar.selectAll("rect")
        .data(function(d) { return d.values;})
        .enter()
        .append("rect");

// Append parent node information (e.g. 'likes') to each rectangle    
// per the SO question referenced above        
rect.attr("metric", function(d, i, j) {
  return rect[j].parentNode.__data__.key;
});

これにより、「いいね:2」などの長方形ごとのツールチップを作成できます。ここまでは順調ですね。

問題は、これと同じ情報をクリックイベントに関連付ける方法であり、以下に基づいています。

rect.on("click", function(d) {
  return _this.onChartClick(d);
});

// or

rect.on("click", this.onChartClick.bind(this));

onChartClickメソッドはバインドされたデータ(d)とチャート実行コンテキスト('this')にアクセスする必要があるため、問題があります。そうでない場合は、実行コンテキストを切り替えてd3.select(this).attr("metric")、onChartClickメソッド内で呼び出すことができます。

私が持っていたもう1つのアイデアは、メトリックを追加のパラメーターとして渡すことでしたが、ここでfunction(d、i、j)を使用するトリックは、クリックイベントが発生するまで実行されないため、機能しないようです。

解決策を提案できますか?

4

3 に答える 3

6

クロージャーを使用して、次のように親データへの参照を保持できます。

bar.each(function(dbar) {            // dbar refers to the data bound to the bar
  d3.select(this).selectAll("rect")
      .on("click", function(drect) { // drect refers to the data bound to the rect
        console.log(dbar.key);       // dbar.key will be either 'likes' or 'dislikes'
      });
});

アップデート:

DOM構造のさまざまなレベルにアクセスするさまざまな方法については、以下を参照してください。ミックスしてマッチ!これのライブバージョンを参照して、.rect divをクリックしてみてください: http://bl.ocks.org/4235050

var data =  [
    {
        key: 'likes',
        values: [{ key: 'blue-frog', value: 1 }, { key: 'goodbye', value: 2 }]
    }, 
    {
        key: 'dislikes',
        values: [{ key: 'blue-frog', value: 3 }, { key: 'goodbye', value: 4 }]
    }];

var chartdivs = d3.select("body").selectAll("div.chart")
    .data([data]) // if you want to make multiple charts: .data([data1, data2, data3])
  .enter().append("div")
    .attr("class", "chart")
    .style("width", "500px")
    .style("height", "400px");

chartdivs.call(chart); // chartdivs is a d3.selection of one or more chart divs. The function chart is responsible for creating the contents in those divs

function chart(selection) { // selection is one or more chart divs
  selection.each(function(d,i) { // for each chartdiv do the following
    var chartdiv = d3.select(this);
    var bar = chartdiv.selectAll(".bar")
        .data(d)
      .enter().append("div")
        .attr("class", "bar")
        .style("width", "100px")
        .style("height", "100px")
        .style("background-color", "red");  

    var rect = bar.selectAll(".rect")
        .data(function(d) { return d.values; })
      .enter().append("div")
        .attr("class", "rect")
        .text(function(d) { return d.key; })
        .style("background-color", "steelblue");

    bar.each(function(dbar) {
      var bardiv = d3.select(this);
      bardiv.selectAll(".rect")
          .on("click", function(drect) { 
            d3.select(this).call(onclickfunc, bardiv);
          });
    });

    function onclickfunc(rect, bar) { // has access to chart, bar, and rect
      chartdiv.style("background-color", bar.datum().key === 'likes' ? "green" : "grey");
      console.log(rect.datum().key); // will print either 'blue-frog' or 'goodbye'
    }
  });
}
于 2012-12-07T03:02:16.893 に答える
0

rect.on("click", this.onChartClick.bind(this));関数を渡していないため、機能しません。関数の戻り値を渡しています(を追加することにより(this))。

thisデータ( )を渡したい場合は、次のことをd試してください。

// assuming you have this somewhere earlier
var onChartClick = function () {}

// change your parent click to
rect.on("click", function(d) {
    return onChartClick.call(this, d);
});
于 2012-12-06T20:08:47.837 に答える
0

別の方法は、オブジェクト/ jsonを渡すか、私の場合はその長方形をイベントに作成して内部にアクセスするクラスインスタンスを渡すことです。

var rect = svgContainer.append("rect");
rect.datum(this);
rect.on('click', function(d){
    alert(d);
    alert(d.id); // etc.
});
于 2018-08-03T13:48:34.497 に答える