繁体   English   中英

D3从堆积条形图到条形图的转换仅在第一次时有效

[英]D3 transition from stacked bar to bar chart only works the first time

我正在尝试创建两个图表,一个堆叠的条形图和一个条形图,每个显示不同的数据集。 但是,当我单击按钮时,我想从堆叠的条形图过渡到条形图,反之亦然。 我编写的代码仅在第一次使用时有效,然后在此之后,当我想从条形图转换回堆叠的条形图时,所有条形图以单个条形图的形式相互堆叠。 有人可以指出我正确的方向,如何从钢筋过渡到堆叠钢筋吗? 任何帮助,将不胜感激。 (我还没有真正弄乱坐标轴,因此它们没有变化是正常的)。

这是当前外观的链接: https : //jhjanicki.github.io/stackbartobar/

下面是我的代码:

 var value = 'stack'; var data = [{ name: "Shihuahuaco", value: 1067, china: 772 }, { name: "Cachimbo", value: 283, china: 1 }, { name: "Estoraque", value: 204, china: 150 }, { name: "Cumala", value: 154, china: 0 }, { name: "Ishpingo", value: 108, china: 3 }, { name: "Huayruro", value: 108, china: 1 }, { name: "Tornillo", value: 61, china: 4 }, { name: "Congona", value: 54, china: 0 }, { name: "Capirona", value: 37, china: 5 }, { name: "Tahuari", value: 33, china: 14 }, { name: "Marupa", value: 33, china: 1 }, { name: "Quinilla", value: 28, china: 4 }, { name: "Azucar huayo", value: 22, china: 15 }, { name: "Protium sp.", value: 19, china: 0 }, { name: "Nogal", value: 15, china: 6 }, { name: "Ana Caspi", value: 14, china: 2 }, { name: "Cedro", value: 14, china: 0 }, { name: "Carapa guianensis", value: 12, china: 0 }, { name: "Leche caspi", value: 12, china: 0 }, { name: "Andiroba", value: 11, china: 0 }, { name: "Copaiba", value: 7, china: 4 }, { name: "Palo baston", value: 6, china: 0 }, { name: "Moena", value: 5, china: 0 }, { name: "Almendro", value: 5, china: 0 }, { name: "Chancaquero", value: 4, china: 0 }, { name: "Caimitillo", value: 3, china: 1 }, { name: "Nogal amarillo", value: 3, china: 0 }, { name: "Couma macrocarpa", value: 3, china: 0 }, { name: "Tulpay", value: 3, china: 0 }, { name: "Carapa", value: 3, china: 0 }, { name: "Dacryodes olivifera", value: 2, china: 0 }, { name: "Capinuri", value: 2, china: 2 }, { name: "Brosimum alicastrum", value: 2, china: 0 }, { name: "Paramachaerium ormosioide", value: 2, china: 0 }, { name: "Brosimum sp.", value: 2, china: 0 }, { name: "Manchinga", value: 2, china: 0 }]; // data for stacked bar var points = [{ 'lon': 105.3, 'lat': 33.5, 'name': 'China', 'GTF': 1024, "ID": "CHN" }, { 'lon': -70.9, 'lat': 18.8, 'name': 'Dominican Republic', 'GTF': 470, "ID": "DOM" }, { 'lon': -101, 'lat': 38, 'name': 'USA', 'GTF': 248, "ID": "USA" }, { 'lon': -102.5, 'lat': 22.7, 'name': 'Mexico', 'GTF': 220, "ID": "MEX" }, { 'lon': 2.98, 'lat': 46, 'name': 'France', 'GTF': 85, "ID": "FRA" } ]; //data for bar var margin = { top: 20, right: 30, bottom: 150, left: 60 }, widthB = 700 - margin.left - margin.right, heightB = 500 - margin.top - margin.bottom; var dataIntermediate = ['value', 'china'].map(function(key, i) { return data.map(function(d, j) { return { x: d['name'], y: d[key] }; }) }) var dataStackLayout = d3.layout.stack()(dataIntermediate); var svg = d3.select("#chart").append("svg") .attr("width", widthB + margin.left + margin.right) .attr("height", heightB + margin.top + margin.bottom) var gBar = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .attr('class', 'gBar'); var x = d3.scale.ordinal() .rangeRoundBands([0, widthB], .2); var y = d3.scale.linear() .range([heightB, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(8) .tickFormat(function(d) { return y.tickFormat(4, d3.format(",d"))(d) }); data.forEach(function(d) { d.value = +d.value; // coerce to number d.china = +d.china; }); x.domain(dataStackLayout[0].map(function(d) { return dx; })); y.domain([0, d3.max(dataStackLayout[dataStackLayout.length - 1], function(d) { return d.y0 + dy; })]).nice(); var layer; var bars; //axes gBar.append("g") .attr("class", "axis") .attr("transform", "translate(0," + (heightB + 10) + ")") .call(xAxis) .selectAll("text") .style('font-size', '14px') .style('font-family', 'Alegreya') .style("text-anchor", "end") .attr("dx", "-0.40em") .attr("dy", ".10em") .attr("transform", function(d) { return "rotate(-65)" }); gBar.append("g") .attr("class", "y axis") .call(yAxis) .selectAll("text") .style('font-size', '16px') .style('font-family', 'Alegreya'); function draw() { if (value == 'stack') { layer = gBar.selectAll(".stack") .data(dataStackLayout); layer.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .style("fill", "none") .remove(); layer.enter().append("g") .attr("class", "stack") .style("fill", function(d, i) { return i == 0 ? '#b4d5c3' : '#ecaeb3'; }); bars = layer.selectAll("rect") .data(function(d) { return d; }); // the "EXIT" set: bars.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .attr("y", y(0)) .attr("height", heightB - y(0)) .style('fill-opacity', 1e-6) .remove(); // the "ENTER" set: bars.enter().append("rect") .transition() .delay(function(d, i) { return 30 * i; }) .duration(3000) .attr("x", function(d) { return x(dx); }) .attr("y", function(d) { return y(dy + d.y0); }) .attr("height", function(d) { return y(d.y0) - y(dy + d.y0); }) .attr("width", x.rangeBand()); // the "UPDATE" set: bars.transition().delay(function(d, i) { return 30 * i; }).duration(1500).attr("x", function(d) { return x(dx); }) .attr("width", x.rangeBand()) // constant, so no callback function(d) here .attr("y", function(d) { return y(dy + d.y0); }) .attr("height", function(d) { return y(d.y0) - y(dy + d.y0); }); } else { // draw bar x.domain(points.map(function(d) { return d.name; })); y.domain([0, 1024]).nice(); bars = layer.selectAll("rect") .data(points); // the "EXIT" set: bars.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .attr("y", y(0)) .attr("height", heightB - y(0)) .style('fill-opacity', 1e-6) .remove(); // the "ENTER" set: bars.enter().append("rect") .transition() .delay(function(d, i) { return 30 * i; }) .duration(3000) .attr("x", function(d) { return x(d.name); }) .attr("y", function(d) { return y(d.GTF); }) .attr("height", function(d) { return heightB - y(d.GTF);; }) .attr("width", x.rangeBand()); // the "UPDATE" set: bars.transition().delay(function(d, i) { return 30 * i; }).duration(1500).attr("x", function(d) { return x(d.name); }) .attr("width", x.rangeBand()) // constant, so no callback function(d) here .attr("y", function(d) { return y(d.GTF); }) .attr("height", function(d) { return heightB - y(d.GTF); }); } } window.onload = draw(); $("#click").on('click', function() { if (value == 'stack') { value = 'bar'; } else { value = 'stack'; } draw(); }); 
 body { font-family: 'Alegreya', serif; } .axis text { font: 10px sans-serif; } .axis path { fill: none; stroke: #000; stroke-width: 0px; shape-rendering: crispEdges; } .axis line { fill: none; stroke: #000; stroke-width: 0.5px; shape-rendering: crispEdges; } .x.axis path { display: none; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://d3js.org/d3.v3.js"></script> <div id="chart"></div> <p id="click"> click here to change </p> 

代码中的问题是您要更改条形图的比例域,但不能将其更改为堆叠的条形图。

因此,应将其放在堆叠条的draw()部分(条件语句)中:

x.domain(dataStackLayout[0].map(function(d) {
  return d.x;
}));

y.domain([0, d3.max(dataStackLayout[dataStackLayout.length - 1],
  function(d) {
    return d.y0 + d.y;
  })]).nice();

这是您所做的更改的代码(我也呼吁x轴):

 var value = 'stack'; var data = [{ name: "Shihuahuaco", value: 1067, china: 772 }, { name: "Cachimbo", value: 283, china: 1 }, { name: "Estoraque", value: 204, china: 150 }, { name: "Cumala", value: 154, china: 0 }, { name: "Ishpingo", value: 108, china: 3 }, { name: "Huayruro", value: 108, china: 1 }, { name: "Tornillo", value: 61, china: 4 }, { name: "Congona", value: 54, china: 0 }, { name: "Capirona", value: 37, china: 5 }, { name: "Tahuari", value: 33, china: 14 }, { name: "Marupa", value: 33, china: 1 }, { name: "Quinilla", value: 28, china: 4 }, { name: "Azucar huayo", value: 22, china: 15 }, { name: "Protium sp.", value: 19, china: 0 }, { name: "Nogal", value: 15, china: 6 }, { name: "Ana Caspi", value: 14, china: 2 }, { name: "Cedro", value: 14, china: 0 }, { name: "Carapa guianensis", value: 12, china: 0 }, { name: "Leche caspi", value: 12, china: 0 }, { name: "Andiroba", value: 11, china: 0 }, { name: "Copaiba", value: 7, china: 4 }, { name: "Palo baston", value: 6, china: 0 }, { name: "Moena", value: 5, china: 0 }, { name: "Almendro", value: 5, china: 0 }, { name: "Chancaquero", value: 4, china: 0 }, { name: "Caimitillo", value: 3, china: 1 }, { name: "Nogal amarillo", value: 3, china: 0 }, { name: "Couma macrocarpa", value: 3, china: 0 }, { name: "Tulpay", value: 3, china: 0 }, { name: "Carapa", value: 3, china: 0 }, { name: "Dacryodes olivifera", value: 2, china: 0 }, { name: "Capinuri", value: 2, china: 2 }, { name: "Brosimum alicastrum", value: 2, china: 0 }, { name: "Paramachaerium ormosioide", value: 2, china: 0 }, { name: "Brosimum sp.", value: 2, china: 0 }, { name: "Manchinga", value: 2, china: 0 }]; var points = [{ 'lon': 105.3, 'lat': 33.5, 'name': 'China', 'GTF': 1024, "ID": "CHN" }, { 'lon': -70.9, 'lat': 18.8, 'name': 'Dominican Republic', 'GTF': 470, "ID": "DOM" }, { 'lon': -101, 'lat': 38, 'name': 'USA', 'GTF': 248, "ID": "USA" }, { 'lon': -102.5, 'lat': 22.7, 'name': 'Mexico', 'GTF': 220, "ID": "MEX" }, { 'lon': 2.98, 'lat': 46, 'name': 'France', 'GTF': 85, "ID": "FRA" }]; var margin = { top: 20, right: 30, bottom: 150, left: 60 }, widthB = 700 - margin.left - margin.right, heightB = 500 - margin.top - margin.bottom; var dataIntermediate = ['value', 'china'].map(function(key, i) { return data.map(function(d, j) { return { x: d['name'], y: d[key] }; }) }) var dataStackLayout = d3.layout.stack()(dataIntermediate); var svgBar = d3.select("#chart").append("svg") .attr("width", widthB + margin.left + margin.right) .attr("height", heightB + margin.top + margin.bottom) var gBar = svgBar.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .attr('class', 'gBar'); var x = d3.scale.ordinal() .rangeRoundBands([0, widthB], .2); var y = d3.scale.linear() .range([heightB, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(8) .tickFormat(function(d) { return y.tickFormat(4, d3.format(",d"))(d) }); data.forEach(function(d) { d.value = +d.value; // coerce to number d.china = +d.china; }); x.domain(dataStackLayout[0].map(function(d) { return dx; })); y.domain([0, d3.max(dataStackLayout[dataStackLayout.length - 1], function(d) { return d.y0 + dy; })]).nice(); var layer; // this part var bars; var gX = gBar.append("g") .attr("class", "axis") .attr("transform", "translate(0," + (heightB + 10) + ")"); gBar.append("g") .attr("class", "y axis") .call(yAxis) .selectAll("text") .style('font-size', '16px') .style('font-family', 'Alegreya'); function draw() { if (value == 'stack') { x.domain(dataStackLayout[0].map(function(d) { return dx; })); y.domain([0, d3.max(dataStackLayout[dataStackLayout.length - 1], function(d) { return d.y0 + dy; })]).nice(); layer = gBar.selectAll(".stack") .data(dataStackLayout); layer.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .style("fill", "none") .remove(); layer.enter().append("g") .attr("class", "stack") .style("fill", function(d, i) { return i == 0 ? '#b4d5c3' : '#ecaeb3'; }); bars = layer.selectAll("rect") .data(function(d) { return d; }); bars.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .attr("y", y(0)) .attr("height", heightB - y(0)) .style('fill-opacity', 1e-6) .remove(); bars.enter().append("rect") .transition() .delay(function(d, i) { return 30 * i; }) .duration(3000) .attr("x", function(d) { return x(dx); }) .attr("y", function(d) { return y(dy + d.y0); }) .attr("height", function(d) { return y(d.y0) - y(dy + d.y0); }) .attr("width", x.rangeBand()); // the "UPDATE" set: bars.transition().delay(function(d, i) { return 30 * i; }).duration(1500).attr("x", function(d) { return x(dx); }) // (d) is one item from the data array, x is the scale object from above .attr("width", x.rangeBand()) // constant, so no callback function(d) here .attr("y", function(d) { return y(dy + d.y0); }) .attr("height", function(d) { return y(d.y0) - y(dy + d.y0); }) .style("fill-opacity", 1); gX.call(xAxis) .selectAll("text") .style('font-size', '14px') .style('font-family', 'Alegreya') .style("text-anchor", "end") .attr("dx", "-0.40em") .attr("dy", ".10em") .attr("transform", function(d) { return "rotate(-65)" }); } else { x.domain(points.map(function(d) { return d.name; })); y.domain([0, 1024]).nice(); // this part bars = layer.selectAll("rect") .data(points); bars.exit() .transition() .delay(function(d, i) { return 30 * i; }) .duration(1500) .attr("y", y(0)) .attr("height", heightB - y(0)) .style('fill-opacity', 1e-6) .remove(); bars.enter().append("rect") .transition() .delay(function(d, i) { return 30 * i; }) .duration(3000) .attr("x", function(d) { return x(d.name); }) .attr("y", function(d) { return y(d.GTF); }) .attr("height", function(d) { return heightB - y(d.GTF);; }) .attr("width", x.rangeBand()); // the "UPDATE" set: bars.transition().delay(function(d, i) { return 30 * i; }).duration(1500).attr("x", function(d) { return x(d.name); }) // (d) is one item from the data array, x is the scale object from above .attr("width", x.rangeBand()) // constant, so no callback function(d) here .attr("y", function(d) { return y(d.GTF); }) .attr("height", function(d) { return heightB - y(d.GTF); }); gX.call(xAxis); } } window.onload = draw(); $("#click").on('click', function() { if (value == 'stack') { value = 'bar'; } else { value = 'stack'; } draw(); }); 
 body { font-family: 'Alegreya', serif; } .axis text { font: 10px sans-serif; } .axis path { fill: none; stroke: #000; stroke-width: 0px; shape-rendering: crispEdges; } .axis line { fill: none; stroke: #000; stroke-width: 0.5px; shape-rendering: crispEdges; } .x.axis path { display: none; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://d3js.org/d3.v3.js"></script> <div id="chart"></div> <button id="click"> click here to change </button> 

PS :除此之外,您还需要在代码中进行许多其他小的更改,以提高性能和设计。 由于这是(现在)正在运行的代码,因此建议您使用标记在Code Review上发布有关如何对其进行改进的其他问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM