簡體   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