【发布时间】:2021-05-21 13:48:45
【问题描述】:
关于创建条形图并显示差异值百分比和线条,我已要求以下帮助,以下是链接:
How to create a % difference arrow line with value in a bar chart using D3.js
我创建了这个线程来寻求帮助以使同一图表更具动态性,以下是我的尝试:
- 以适合任何分辨率的方式使其动态化,即做出响应(Div 的任何宽度和高度都可以呈现图表)
- 尝试做反向差分计算。(目前是计算正向差分计算并显示正向箭头,但反向计算需要反向显示箭头)
(已编辑: 例如:计算基本上会从最后一根柱线开始,然后一直持续到第一根柱线。例如:(6453-7345)/7345 = -12% 和 (6453-5388)/6453 = -17%。)
下面是代码:
var barData = [{
"Time": "2019",
"Value": 5388
},
{
"Time": "2020",
"Value": 6453
},
{
"Time": "2021",
"Value": 4345
},
{
"Time": "2022",
"Value": 7345
},
{
"Time": "2023",
"Value": 5345
}];
// Consider this width and Height are dynamic for div "graphID" because I am trying to responsive design
const divWidth = 700,
divHeight = 700;
//Adding Margin to Viz Area
var margin = {top: 30, right: 50, bottom: 0, left: 50},
width = parseInt(divWidth,10) - margin.left - margin.right,
height = parseInt(divHeight,10) - margin.top - margin.bottom;
//To add svg in the visualization node i.e Dome node
const svg = d3.select("#graphID").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Adding x axis width i.e based on Viz Width
const xScale = d3.scaleBand()
.domain(barData.map(d => d.Time))
.range([0, width]);
const xAxis = d3.axisBottom(xScale);
//Adding g attribute to svg for x axis
svg.append('g')
//.attr('transform', 'translate(20,170)')
.attr("transform", "translate(10," + (height - 50) + ")")
.call(xAxis);
/*
//To get the Max value from an json object
const maxVal = barData.reduce((acc, shot) => acc = acc > shot.Value ? acc : shot.Value, 0);
const valMax = Math.max.apply(barData, barData.map(function(o) { return o.Value; }));
alert(valMax);
const yScale = d3.scaleLinear()
.domain([0, maxVal+(maxVal/2)])
.range([150, 0]);
*/
const yAxisMax = Math.max.apply(barData, barData.map(function(o) { return o.Value; }));
const yScale = d3.scaleLinear()
.domain([0, yAxisMax+(yAxisMax/2)])
.range([height, 0]);
const yAxis = d3.axisLeft(yScale).ticks(4);
svg.append('g')
//.attr('transform', 'translate(50,170)')
.attr("transform", "translate(10,-50)")
//.attr("transform", "translate(20," + (height - 50) + ")")
.call(yAxis);
const bars = svg.selectAll('g.bar')
.data(barData)
.enter()
.append('g')
.classed('bar', true)
.attr('transform', d => `translate(${xScale(d.Time) + 50 + xScale.bandwidth() / 20}, 170)`)
bars.append('rect')
.attr('x', -10)
.attr('width', 40)
.attr('y', d => -height + yScale(d.Value))
.attr('height', d => yScale(d.Value) )
.style('fill', 'blue')
bars.append('text')
.text(d => d.Value)
.attr('text-anchor', 'middle')
.attr('y', d => -(height - 55) + yScale(d.Value))
bars.filter((d, i) => i < barData.length - 1)
.append('path')
.attr('d', (d, i) => `M 5,${-170 + yScale(d.Value)} V ${-210 + yScale(d.Value)} H ${xScale.bandwidth() - 5} V ${-180 + yScale(barData[i + 1].Value)}`)
.style('stroke', 'gray')
.style('fill', 'none')
.attr('marker-end', 'url(#arrowhead)')
bars.filter((d, i) => i < barData.length - 1)
.append('rect')
.attr('x', 15)
.attr('y', d => -220 + yScale(d.Value))
.attr('width', xScale.bandwidth() - 30)
.attr('height', 20)
.attr('rx', 10)
.style('fill', 'white')
.style('stroke', 'gray');
bars.filter((d, i) => i < barData.length - 1)
.append('text')
.text((d, i) => `${barData[i + 1].Value > d.Value ? '+' : '-'}${Math.round((barData[i + 1].Value / d.Value * 100) - 100)}%`)
.attr('x', xScale.bandwidth() / 2)
.attr('y', d => -207 + yScale(d.Value))
.attr('text-anchor', 'middle')
.style('fill', 'black');
#graphID
{
width:500px;
height:700px
}
text {
font-size: 12px;
font-family: "Ubuntu";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="graphID" width=500 height=700>
</div>
【问题讨论】:
-
我可以理解需要响应大小 (1) 以及第一个和最后一个 (3) 之间的差异。我不明白的是问题2(反向差异计算)。你如何定义哪一对值应该显示反向差异?
-
好的,对于问题 2,计算基本上是从最后一根柱线开始,然后一直持续到第一根柱线。例如:(6453-7345)/7345 = -12% 和 (6453-5388)/6453 = -17%。我将编辑帖子并在其中添加相同的内容。我希望这现在很清楚。如果没有,请告诉我。 :)
-
我了解如何计算,我不了解如何显示两个方向的变化......我也认为一次完成所有问题需要大量编码。我建议将问题分为两个步骤(一个用于响应性,第二个用于差异计算),否则将很难管理...
-
是的,明白,这就是为什么我一开始就试图让它响应。我只分享了第一个问题相关的代码。其他问题将在稍后讨论。您能否帮助我进行响应式实施。我在努力,但在挣扎。您的帮助将不胜感激。
标签: javascript html css d3.js