繁体   English   中英

D3.js 径向条形图,条形为线

[英]D3.js radial barplot with bars as lines

我想构建一个 D3.js 径向条形图。 我见过的所有示例代码都显示了这种图表,条形图绘制为“楔形”。 是否可以告诉 d3.js 将条形绘制为直线而不是楔形?

此图像是我希望条形图如何显示在图表上的示例

r

例如,这里是我生成条形图的代码。

 const data = [{ "name": "Burj Khalifa", "height": "350" }, { "name": "Shanghai Tower", "height": "263.34" }, { "name": "Abraj Al-Bait Clock Tower", "height": "254.04" }, { "name": "Ping An Finance Centre", "height": "253.20" }, { "name": "Lotte World Tower", "height": "230.16" }, { "name": "Burj Khalifa 2", "height": "350" }, { "name": "Shanghai Tower 2", "height": "263.34" }, { "name": "Abraj Al-Bait Clock Tower 2", "height": "254.04" }, { "name": "Ping An Finance Centre 2", "height": "253.20" } ] data.forEach((d) => { d.height = Number(d.height) }) const heightExtent = d3.extent(data, d => d.height) const bars = data.map(d => d.name) const containerWidth = 400 const containerHeight = 800 const y = d3.scaleLinear() .domain([0, heightExtent[1]]) .range([0, containerHeight]) const x = d3.scaleBand() .domain(bars) .range([0, containerWidth]) .paddingInner(0.02) .paddingOuter(0) const colourScale = d3.scaleOrdinal(d3.schemeBlues[data.length]) const svg = d3.select("#chart-area").append("svg") .attr("width", containerWidth) .attr("height", containerHeight) const buildings = svg.selectAll('rect').data(data) buildings.enter().append('rect') .attr('x', (d, i) => x(d.name)) .attr('y', (d, i) => { return containerHeight - y(d.height) }) .attr('width', x.bandwidth()) .attr('height', (d, i) => y(d.height)) .attr('fill', (d, i) => colourScale(d.name)) const labels = svg.selectAll('text').data(data) labels.enter().append('text') .attr('text-anchor', 'end') .attr('x', (d, i) => (x(d.name) + (x.bandwidth() / 2))) .attr('y', (d, i) => containerHeight - 10) .attr('writing-mode', 'tb') .attr('fill', 'white') .text((d, i) => (d.name + ' - ' + d.height + 'm'))
 <!-- Bootstrap grid setup --> <div class="container"> <div class="row"> <div id="chart-area"></div> </div> </div> <!-- External JS libraries --> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

考虑以下:

 const data = [{ "name": "Burj Khalifa", "height": "350" }, { "name": "Shanghai Tower", "height": "263.34" }, { "name": "Abraj Al-Bait Clock Tower", "height": "254.04" }, { "name": "Ping An Finance Centre", "height": "253.20" }, { "name": "Lotte World Tower", "height": "230.16" }, { "name": "Burj Khalifa 2", "height": "350" }, { "name": "Shanghai Tower 2", "height": "263.34" }, { "name": "Abraj Al-Bait Clock Tower 2", "height": "254.04" }, { "name": "Ping An Finance Centre 2", "height": "253.20" } ] data.forEach((d) => { d.height = Number(d.height) }) const heightExtent = d3.extent(data, d => d.height) const bars = data.map(d => d.name) const containerWidth = 700 const containerHeight = 300 const barWidth = 16 const radius = Math.min(containerWidth / 2, containerHeight / 2) - barWidth * 4; const y = d3.scaleLinear() .domain([0, heightExtent[1]]) .range([0, radius]) const angle = d3.scaleBand() .domain(bars) .range([0, 360]) .paddingInner(0.02) .paddingOuter(0) const colourScale = d3.scaleOrdinal(d3.schemeBlues[data.length]) const svg = d3.select("#chart-area").append("svg") .attr("width", containerWidth) .attr("height", containerHeight) const buildings = svg.selectAll('rect').data(data) buildings.enter().append('rect') .attr('x', - barWidth / 2) .attr('y', barWidth * 2) .attr('width', barWidth) .attr('height', (d, i) => y(d.height)) .style('transform', (d, i) => `translate(${containerWidth / 2}px, ${containerHeight / 2}px) rotate(${angle(d.name)}deg)`) .attr('fill', (d, i) => colourScale(d.name)) const labels = svg.selectAll('text').data(data) labels.enter().append('text') .attr('x', -barWidth / 2) .attr('text-anchor', (d, i) => { const degrees = angle(d.name); if(10 <= degrees && degrees <= 170) { return 'end'; } if(190 <= degrees && degrees <= 350) { return 'start'; } return 'middle'; }) .style('transform', (d, i) => { const xBase = containerWidth / 2; const yBase = containerHeight / 2; const degrees = angle(d.name); const radians = (degrees + 90) / 360 * 2 * Math.PI; const barHeight = y(d.height) + 2.5 * barWidth; const yOffset = Math.sin(radians) * barHeight; const xOffset = Math.cos(radians) * barHeight; return `translate(${xBase + xOffset}px, ${yBase + yOffset}px)`; }) .text((d, i) => (d.name + ' - ' + d.height + 'm'))
 <!-- Bootstrap grid setup --> <div class="container"> <div class="row"> <div id="chart-area"></div> </div> </div> <!-- External JS libraries --> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

我已更改 x 比例以返回 0 到 360 之间的数字(旋转度数),然后将所有条放在中间,按度数旋转。 唯一的问题是很难阅读旋转的文本,更难旋转文本,因为它的宽度是未知的。 因此,我展示了如何使用正弦和余弦函数将文本放在每个小节的末尾。

暂无
暂无

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

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