I am using d3.js but I am unable to show both values together on graph that is positive values above the x axis and negative value below x axis ...
I tried below code
var bar = g.selectAll(".bar").data(data);
var barColorClass = 'blue-bar';
var transitionOrigin = D3Graph.height - 1;
var rect = bar.enter().append("rect")
.attr("class", "bar "+barColorClass)
.attr("x", function(d, i) { return i * unit; })
.attr("y", function(d) { return transitionOrigin;})
.attr("width", unit);
rect.transition(t)
.attr("height", function(d) {
return (y(d.amount) < 0) ? (D3Graph.height + 3) : (D3Graph.height - y(d.amount));
}).attr("y", function(d) {
return (y(d.amount) < 0) ? (-1 * 3) : y(d.amount);
});
In a canonical example you would adjust the y
and height
of the rects based on if they are positive or negative:
.attr('y', (d) => d.y > 0 ? y(d.y) : y(0))
.attr('height', (d) => d.y > 0 ? y(0) - y(d.y) : y(d.y) - y(0))
Full example:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.js"></script>
</head>
<body>
<div id="chart"></div>
<script>
const margin = {
top: 30,
right: 30,
bottom: 70,
left: 60
},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
const svg = d3
.select('#chart')
.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 + ')');
const data = [{
x: 'one',
y: 10,
},
{
x: 'two',
y: -10,
},
{
x: 'three',
y: 5,
},
{
x: 'four',
y: -5,
},
{
x: 'five',
y: 15,
},
{
x: 'six',
y: -15,
},
];
// X axis
const x = d3
.scaleBand()
.range([0, width])
.domain(
data.map((d) => d.x)
)
.padding(0.2);
svg
.append('g')
.attr('transform', 'translate(0,' + height + ')')
.call(d3.axisBottom(x))
.selectAll('text')
.attr('transform', 'translate(-10,0)rotate(-45)')
.style('text-anchor', 'end');
// Add Y axis
const y = d3.scaleLinear().domain(d3.extent(data.map((d) => d.y))).range([height, 0]);
svg.append('g').call(d3.axisLeft(y));
// Bars
svg
.selectAll(null)
.data(data)
.enter()
.append('rect')
.attr('x', (d) => x(d.x))
.attr('y', (d) => d.y > 0 ? y(d.y) : y(0))
.attr('width', x.bandwidth())
.attr('height', (d) => d.y > 0 ? y(0) - y(d.y) : y(d.y) - y(0))
.attr('fill', 'steelblue');
</script>
</body>
</html>