繁体   English   中英

简单的D3.js条形图:“ g”组的位置和尺寸被弄乱了

[英]Simple D3.js bar chart : group “g” position and dimensions messed up

我是D3.js的新手,试图制作一个简单的条形图。 这是我的POC:

 <!DOCTYPE html> <html> <head></head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.js"></script> <script type="text/javascript"> dataSet = [ { 'year': 1851, 'data': -5.0 }, { 'year': 1861, 'data': -4.5 }, { 'year': 1871, 'data': -3.2 }, { 'year': 1881, 'data': -2.8 }, { 'year': 1891, 'data': -1.7 }, { 'year': 1901, 'data': -1.0 }, { 'year': 1911, 'data': 1.2 }, { 'year': 1921, 'data': 2.5 }, { 'year': 1931, 'data': 3.0 }, { 'year': 1941, 'data': 3.9 }, { 'year': 1951, 'data': 4.7 }, ]; console.log(dataSet); const widthSvg = 1024; const heightSvg = 768; const svg = d3.select('body') .append('svg') .attr('width', widthSvg) .attr('height', heightSvg); const outerAxisPadding = 70; const yAxisWidth = 20; const xAxisHeight = 20; const margins = { left: outerAxisPadding + yAxisWidth, top: outerAxisPadding, bottom: outerAxisPadding + xAxisHeight, right: outerAxisPadding }; const graphArea = { left: margins.left, top: margins.top, right: widthSvg - margins.right, bottom: heightSvg - margins.bottom, width: 0, height: 0 }; graphArea.width = graphArea.right - graphArea.left; graphArea.height = graphArea.bottom - graphArea.top; const dataGroup = svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + graphArea.top + ')') .attr('width', graphArea.width - 10) .attr('height', graphArea.height - 10); const xScale = d3.scaleLinear() .domain([ d3.min( dataSet.map(d => d.year) ) - 15, d3.max( dataSet.map(d => d.year) ) + 15 ]) .range([0, graphArea.width]); const yScaleForAxis = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => d.data)), d3.max(dataSet.map(d => d.data)) ]) .nice() .range([graphArea.height, 0]); const yScaleForValues = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => Math.abs(d.data))), d3.max(dataSet.map(d => Math.abs(d.data))) ]) .nice() .range([0, graphArea.height / 2]); // for debug: dataSet.forEach(d => console.log(d.year + ' ' + d.data + ' ' + yScaleForValues(d.data))); const xAxis = d3.axisBottom(xScale); const yAxis = d3.axisLeft(yScaleForAxis); // add yAxis nodes svg.append('g') .attr('transform', 'translate(' + outerAxisPadding + ',' + graphArea.top + ')') .call(yAxis); // add xAxis nodes svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + (heightSvg - outerAxisPadding) + ')') .call(xAxis); dataGroup.selectAll('rect') .data(dataSet) .enter() .append('rect') .text((d, i) => d.year + ' ' + d.data) // just for information / debugging .attr('fill', 'blue') .attr('x', (d, i) => xScale(d.year)) .attr('y', (d, i) => { if (d.data > 0) { return graphArea.height - yScaleForValues(0) - yScaleForValues(d.data); } else { return graphArea.height - yScaleForValues(0); } }) .attr('width', '15') .attr('height', (d, i) => yScaleForValues(Math.abs(d.data))); </script> </body> </html> 

我不知道它是否结构合理或良好做法。 这里的目标是将dataSet数组注入rects中,year字段为x轴,data字段为y轴。

但是,如您所见,问题在于应该包含rect的dataGroup的位置和尺寸错误。

谢谢

终于使它工作了,完全不同的版本:

 <!DOCTYPE html> <html> <head></head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.js"></script> <script type="text/javascript"> dataSet = [ { 'year': 1831, 'data': -6.9 }, { 'year': 1841, 'data': -5.7 }, { 'year': 1851, 'data': -5.0 }, { 'year': 1861, 'data': -4.5 }, { 'year': 1871, 'data': -3.2 }, { 'year': 1881, 'data': -2.8 }, { 'year': 1891, 'data': -1.7 }, { 'year': 1901, 'data': -1.0 }, { 'year': 1911, 'data': 1.2 }, { 'year': 1921, 'data': 2.5 }, { 'year': 1931, 'data': 3.0 }, { 'year': 1941, 'data': 3.9 }, { 'year': 1951, 'data': 4.7 }, ]; console.log(dataSet); const widthSvg = 1024; const heightSvg = 768; const svg = d3.select('body') .append('svg') .attr('width', widthSvg) .attr('height', heightSvg); const outerAxisPadding = 70; const yAxisWidth = 20; const xAxisHeight = 20; const margins = { left: outerAxisPadding + yAxisWidth, top: outerAxisPadding, bottom: outerAxisPadding + xAxisHeight, right: outerAxisPadding }; const graphArea = { left: margins.left, top: margins.top, right: widthSvg - margins.right, bottom: heightSvg - margins.bottom, width: 0, height: 0 }; graphArea.width = graphArea.right - graphArea.left; graphArea.height = graphArea.bottom - graphArea.top; const dataGroup = svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + graphArea.top + ')') .attr('width', graphArea.width - 10) .attr('height', graphArea.height - 10); const xScale = d3.scaleLinear() .domain([ d3.min( dataSet.map(d => d.year) ) - 15, d3.max( dataSet.map(d => d.year) ) + 15 ]) .range([0, graphArea.width]); const yScaleForAxis = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => d.data)), d3.max(dataSet.map(d => d.data)) ]) .nice() .range([graphArea.height, 0]); const yScaleForValues = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => d.data)), d3.max(dataSet.map(d => d.data)) ]) .nice() .range([0, graphArea.height]); // for debug: dataSet.forEach(d => console.log(d.year + ' ' + d.data + ' ' + yScaleForValues(d.data))); const xAxis = d3.axisBottom(xScale); const yAxis = d3.axisLeft(yScaleForAxis); // add yAxis nodes svg.append('g') .attr('transform', 'translate(' + outerAxisPadding + ',' + graphArea.top + ')') .call(yAxis); // add gridlines svg.append('g') .attr('transform', 'translate(' + margins.left + ',' + graphArea.top + ')') .call(yAxis.tickFormat(data => '').tickSize(-graphArea.width)); // add xAxis nodes svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + (heightSvg - outerAxisPadding) + ')') .call(xAxis); dataGroup.selectAll('rect') .data(dataSet) .enter() .append('rect') .text((d, i) => d.year + ' ' + d.data) // just for information / debugging .attr('fill', 'blue') .attr('x', (d, i) => xScale(d.year)) .attr('y', (d, i) => { if (d.data > 0) { return graphArea.height - yScaleForValues(0) - (yScaleForValues(d.data) - yScaleForValues(0)); // can shorten maths :p } else { return graphArea.height - yScaleForValues(0); } }) .attr('width', '15') .attr('height', (d, i) => { if (d.data > 0) { return yScaleForValues(d.data) - yScaleForValues(0); } else { return yScaleForValues(0) - yScaleForValues(d.data); } }); </script> </body> </html><!DOCTYPE html> <html> <head></head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.js"></script> <script type="text/javascript"> dataSet = [ { 'year': 1831, 'data': -6.9 }, { 'year': 1841, 'data': -5.7 }, { 'year': 1851, 'data': -5.0 }, { 'year': 1861, 'data': -4.5 }, { 'year': 1871, 'data': -3.2 }, { 'year': 1881, 'data': -2.8 }, { 'year': 1891, 'data': -1.7 }, { 'year': 1901, 'data': -1.0 }, { 'year': 1911, 'data': 1.2 }, { 'year': 1921, 'data': 2.5 }, { 'year': 1931, 'data': 3.0 }, { 'year': 1941, 'data': 3.9 }, { 'year': 1951, 'data': 4.7 }, ]; console.log(dataSet); const widthSvg = 1024; const heightSvg = 768; const svg = d3.select('body') .append('svg') .attr('width', widthSvg) .attr('height', heightSvg); const outerAxisPadding = 70; const yAxisWidth = 20; const xAxisHeight = 20; const margins = { left: outerAxisPadding + yAxisWidth, top: outerAxisPadding, bottom: outerAxisPadding + xAxisHeight, right: outerAxisPadding }; const graphArea = { left: margins.left, top: margins.top, right: widthSvg - margins.right, bottom: heightSvg - margins.bottom, width: 0, height: 0 }; graphArea.width = graphArea.right - graphArea.left; graphArea.height = graphArea.bottom - graphArea.top; const dataGroup = svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + graphArea.top + ')') .attr('width', graphArea.width - 10) .attr('height', graphArea.height - 10); const xScale = d3.scaleLinear() .domain([ d3.min( dataSet.map(d => d.year) ) - 15, d3.max( dataSet.map(d => d.year) ) + 15 ]) .range([0, graphArea.width]); const yScaleForAxis = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => d.data)), d3.max(dataSet.map(d => d.data)) ]) .nice() .range([graphArea.height, 0]); const yScaleForValues = d3.scaleLinear() .domain([ d3.min(dataSet.map(d => d.data)), d3.max(dataSet.map(d => d.data)) ]) .nice() .range([0, graphArea.height]); // for debug: dataSet.forEach(d => console.log(d.year + ' ' + d.data + ' ' + yScaleForValues(d.data))); const xAxis = d3.axisBottom(xScale); const yAxis = d3.axisLeft(yScaleForAxis); // add yAxis nodes svg.append('g') .attr('transform', 'translate(' + outerAxisPadding + ',' + graphArea.top + ')') .call(yAxis); // add gridlines svg.append('g') .attr('transform', 'translate(' + margins.left + ',' + graphArea.top + ')') .call(yAxis.tickFormat(data => '').tickSize(-graphArea.width)); // add xAxis nodes svg.append('g') .attr('transform', 'translate(' + graphArea.left + ',' + (heightSvg - outerAxisPadding) + ')') .call(xAxis); dataGroup.selectAll('rect') .data(dataSet) .enter() .append('rect') .text((d, i) => d.year + ' ' + d.data) // just for information / debugging .attr('fill', 'blue') .attr('x', (d, i) => xScale(d.year)) .attr('y', (d, i) => { if (d.data > 0) { return graphArea.height - yScaleForValues(0) - (yScaleForValues(d.data) - yScaleForValues(0)); // can shorten maths :p } else { return graphArea.height - yScaleForValues(0); } }) .attr('width', '15') .attr('height', (d, i) => { if (d.data > 0) { return yScaleForValues(d.data) - yScaleForValues(0); } else { return yScaleForValues(0) - yScaleForValues(d.data); } }); </script> </body> </html> 

我仍然对任何评论/批评都感兴趣。

暂无
暂无

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

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