2017-12-13 14 views
1

私は数ヶ月間d3 v4で作業しており、多くの研究を行っています。私は最終的にデータ結合コンセプトを理解していますが、グループ化された棒グラフを更新する方法を理解しようとすると、棒グラフの棒グラフを更新および削除するにはどうすればよいですか?

私の問題は、結合を実行するときに正しいSVG要素を選択しないため、update()exit()のメソッドが常に空のセットを返すことです。ここに私のコードは、d3ブロックに基づいています:Codepenラインを参照してください#135ここですべての魔法はと思われるが起こっていると仮定。

/* Based on https://bl.ocks.org/mbostock/3887051 */ 
 

 
var svg = d3.select("svg"), 
 
    margin = { top: 20, right: 20, bottom: 100, left: 40 }, 
 
    width = +svg.attr("width") - margin.left - margin.right, 
 
    height = +svg.attr("height") - margin.top - margin.bottom, 
 
    g = svg 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var formatTime = d3.timeFormat("%X"); 
 
var legendKeys = new Map(); 
 
var x0 = d3 
 
    .scaleBand() 
 
    .rangeRound([0, width]) 
 
    .paddingInner(0.1); 
 

 
var x1 = d3.scaleBand().padding(0.05); 
 

 
var y = d3.scaleLinear().rangeRound([height, 0]); 
 

 
var z = d3 
 
    .scaleOrdinal() 
 
    .range([ 
 
    "#98abc5", 
 
    "#8a89a6", 
 
    "#7b6888", 
 
    "#6b486b", 
 
    "#a05d56", 
 
    "#d0743c", 
 
    "#ff8c00" 
 
    ]); 
 

 
var data = []; 
 
for (var i = 0; i < 5; i++) { 
 
    generateData(); 
 
} 
 

 
var keys = Object.keys(data[0].y); 
 
keys.forEach(k => legendKeys.set(".data-" + k.replace(/ /g, ""))); 
 
g.append("g").attr("class", "bars"); 
 

 
var xAxis = g 
 
    .append("g") 
 
    .attr("class", "x--axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.axisBottom(x0).tickFormat(formatTime)); 
 

 
var yAxis = g 
 
    .append("g") 
 
    .attr("class", "y--axis") 
 
    .call(d3.axisLeft(y).ticks(null, "s")); 
 

 
var legend = g 
 
    .append("g") 
 
    .attr("font-family", "sans-serif") 
 
    .attr("font-size", 8) 
 
    .attr("text-anchor", "end") 
 
    .attr("class", "legend") 
 
    .selectAll("g") 
 
    .data(keys.slice()) 
 
    .enter() 
 
    .append("g") 
 
    .attr("transform", function(d, i) { 
 
    return "translate(0," + i * 20 + ")"; 
 
    }); 
 

 
legend 
 
    .append("rect") 
 
    .attr("x", width - 19) 
 
    .attr("width", 19) 
 
    .attr("height", 19) 
 
    .attr("style", "cursor:pointer") 
 
    .attr("fill", z) 
 
    .on("click", function(d) { 
 
    var key = ".data-" + d.replace(/ /g, ""); 
 
    // determine if current line is visible 
 
    var active = legendKeys.get(key) ? false : true, 
 
     newOpacity = active ? 0 : 1; 
 
    // hide or show the elements 
 
    d3.selectAll(key).style("opacity", newOpacity); 
 
    // update whether or not the elements are active 
 
    legendKeys.set(key, active); 
 
    this.style.opacity = active ? 0.5 : 1; 
 
    }); 
 

 
legend 
 
    .append("text") 
 
    .attr("x", width - 24) 
 
    .attr("y", 9.5) 
 
    .attr("dy", "0.32em") 
 
    .text(function(d) { 
 
    return d; 
 
    }); 
 

 
window.setInterval(() => { 
 
    generateData(); 
 
    if (data.length > 14) { 
 
    data.shift(); 
 
    } 
 
    updateChart(); 
 
}, 1000); 
 

 
function updateChart() { 
 
    x0.domain(
 
    data.map(function(d) { 
 
     return d.x; 
 
    }) 
 
); 
 
    x1.domain(keys).rangeRound([0, x0.bandwidth()]); 
 
    y 
 
    .domain([ 
 
     0, 
 
     d3.max(data, function(d) { 
 
     return d3.max(keys, function(key) { 
 
      return d.y[key]; 
 
     }); 
 
     }) 
 
    ]) 
 
    .nice(); 
 

 
    d3.select(".x--axis") 
 
    .transition() 
 
    .call(d3.axisBottom(x0).tickFormat(formatTime)); 
 

 
    d3.select(".y--axis") 
 
    .transition() 
 
    .call(d3.axisLeft(y)); 
 

 
    var barGroups = g 
 
    .select(".bars") 
 
    .selectAll(".barGroup") 
 
    .data(data); 
 

 
    barGroups 
 
    .enter() 
 
    .append("g") 
 
    .attr("transform", function(d) { 
 
     return "translate(" + x0(d.x) + ",0)"; 
 
    }) 
 
    .attr("class", "barGroup") 
 
    .selectAll("rect") 
 
    .data(function(d) { 
 
     return keys.map(function(key) { 
 
     return { key: key, value: d.y[key] }; 
 
     }); 
 
    }) 
 
    .enter() 
 
    .append("rect") 
 
    .attr("x", function(d) { 
 
     return x1(d.key); 
 
    }) 
 
    .attr("y", function(d) { 
 
     return y(d.value); 
 
    }) 
 
    .attr("width", x1.bandwidth()) 
 
    .attr("height", function(d) { 
 
     return height - y(d.value); 
 
    }) 
 
    .attr("class", function(d) { 
 
     return "data-" + d.key.replace(/ /g, ""); 
 
    }) 
 
    .attr("fill", function(d) { 
 
     return z(d.key); 
 
    }) 
 
    .merge(barGroups) 
 
    .attr("width", x1.bandwidth()) 
 
    .attr("height", function(d) { 
 
     return height - y(d.value); 
 
    }) 
 
    .attr("x", function(d) { 
 
     return x1(d.key); 
 
    }) 
 
    .attr("y", function(d) { 
 
     return y(d.value); 
 
    }); 
 

 
    // Exit 
 
    var old = barGroups 
 
    .exit() 
 
    .remove(); 
 

 
    // Release memory for elements that were removed 
 
    old = null; 
 
} 
 

 
function generateData() { 
 
    var lastDate = new Date(); 
 
    if (data.length > 0) { 
 
    lastDate = new Date(data[data.length - 1].x); 
 
    } 
 
    lastDate.setHours(lastDate.getHours() + 1); 
 
    
 
    data.push({ 
 
    x: lastDate, 
 
    y: { 
 
     A: d3.randomUniform(0, 100)(), 
 
     B: d3.randomUniform(0, 100)(), 
 
     C: d3.randomUniform(0, 100)() 
 
    } 
 
    }); 
 
}
/* Based on https://bl.ocks.org/mbostock/3887051 */ 
 
rect.bar { 
 
    fill: steelblue; 
 
} 
 

 
text { 
 
    fill: #000; 
 
    font: 11px sans-serif; 
 
    font-weight:500; 
 
} 
 

 
/* body { 
 
    background-color: #f00; 
 
} */ 
 

 
.legend rect:hover { 
 
    stroke-width:0.5; 
 
    stroke: black; 
 
} 
 

 
svg { 
 
    background-color:#eee; 
 
    shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script> 
 
<!-- Based on https://bl.ocks.org/mbostock/3887051 --> 
 
<svg width="900" height="400"></svg>

+0

グループが正常に更新されているように見えるのは、更新していないバーです。彼らは独自の更新パターンが必要になります。 –

+0

@ RyanMortonどうすればいいの? – RMS

+0

この質問に対する回答(https://stackoverflow.com/questions/38921456/d3-updating-x-axis-groups-on-grouped-bar-chart)には、2つの変数(状態とバー)があり、両方の変数更新パターンに従います。私はそれが一般的に何が行われているかを示していると思う。 –

答えて

0

私はグループ化された棒グラフを更新するために使用し、このパターンを提供しています。あなたのコードを深く見ていなくても、それはおそらく適応することができます。

//update pattern for bar chart 
    var groups = this.plot.selectAll('.bar-group').data(data, function(d) { return d; }); 

    //EXIT bars no longer in the data 
    groups.exit() 
    .transition() 
     .duration(300) 
    .remove(); 

    //ENTER bars with new data 
    var bars = groups.enter().append("g") 
      .attr('class', 'bar-group') 
      .attr("transform", function(d) { return "translate(" + that.x0Scale(d[that.x_var]) + ",0)"; }) 
      .merge(groups) 
      .selectAll('rect') 
      .data(function(d) { return that.grouping.map(function(key) { return {key: key, value: +d[key]}; }); }); 

    //EXIT bars in group just in case that changed 
    bars.exit().transition().duration(300).attr('height', 0).attr("y", that.yScale(0)).remove() 

    bars.enter().append("rect") 
      .attr('class', 'bar') 
      .attr("x", function(d) { return that.x1Scale(d.key); }) 
      .attr("y", that.yScale(0)); 
     .merge(bars) 
     .transition().duration(500) 
      .attr("x", function(d) { return that.x1Scale(d.key); }) 
      .attr("y", function(d) { return that.yScale(Math.max(0, d.value)); }) 
      .attr("width", d3.min([that.x1Scale.bandwidth(), 200])) 
      .attr("height", function(d) { return Math.abs(that.yScale(0)- that.yScale(d.value)); }) 
      .attr("fill", function(d) { return that.zScale(d.key); }) 
      .attr("opacity", 0.85); 
+0

私はあなたの例を見直した後でもこれを得ることができません。私はこれを反映するために[Codepen](https://codepen.io/restlessmindsstudio/pen/KyYBLz)を更新しました。 – RMS

+0

最初のデータ結合にキーを指定せず、グループをマージしませんでした。私はcodepenを働かせることができるかどうか見てみましょう。 –

+0

これはあなたが気にしていたことですか?https://codepen.io/mortonanalytics/pen/baRZQd –

関連する問題