Reputation: 1637
I am trying to draw a bar chart that will have variable width(based on Weight field in json) and height(based on frequency field in json) for bars based on the json data.
currently I am getting some result, but the there is some gap between bars. Seems I am doing the calculations for X or Width wrong.
Can someone point me in the right direction?
https://i.sstatic.net/mD92Z.jpg
The data looks like below.
var data = [{
"letter": "A",
"Weight": 10,
"frequency": 60,
"xPos": 2.5
},
{
"letter": "B",
"Weight": 10,
"frequency": 25,
"xPos": 15
},
{
"letter": "C",
"Weight": 20,
"frequency": 55,
"xPos": 40
}
];
i have a codepen for the same below.
https://codepen.io/poorJSDev/pen/vbReOm
Upvotes: 1
Views: 1131
Reputation: 2896
Since you need to know both current entry weight (for the width), as well as the sum of all previous entries' weights (for the offset), a pie layout seems like an unexpectedly decent fit for the task (since it provides start and end angles for the slices). All you need to do is to map the angle to the width.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
// Feel free to change or delete any of the code you see in this editor!
var svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 200)
var data = [{
freq: 60,
weight: 10
}, {
freq: 25,
weight: 10
}, {
freq: 55,
weight: 20
}];
var xScale = d3.scaleLinear()
.domain([0, Math.PI * 2])
.range([0, 500]);
var yScale = d3.scaleLinear()
.domain([0, 80])
.range([200, 0]);
var pie = d3.pie()
.sortValues(null)
.value(function(d){ return d.weight; });
var adjustedData = pie(data);
var rects = svg.selectAll('rect')
.data(adjustedData);
rects.enter()
.append('rect')
.style('fill', 'blue')
.style('stroke', 'black')
.merge(rects)
.attr('x', function(d) { return xScale(d.startAngle); })
.attr('width', function(d) { return xScale(d.endAngle) - xScale(d.startAngle); })
.attr('y', function(d) { return yScale(d.data.freq); })
.attr('height', function(d) { return yScale(0) - yScale(d.data.freq); });
</script>
</body>
Upvotes: 2