Published
Edited
Jun 23, 2022
1 star
Insert cell
Insert cell
Insert cell
Insert cell
chart1.update(periodData)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
HorizontalBarChart = (data, props) => {
const [width, height] = props.size;
const [xKey, yKey] = props.axisKeys;
const animate = props.animate;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("font-size", "0.625rem")
.attr("font-family", "sans-serif")
.attr("font-weight", "bold");

let topContainer = svg
.selectAll(".top-container")
.data([0])
.enter()
.append("g")
.attr("class", "top-container")
.attr("transform", "translate(30,20)")

const margin = {bottom: 25, right: 50}
const xDomain = props.domain || [0, d3.max(data, d => d[xKey])];
const xScale = d3.scaleLinear()
.domain(xDomain)
.range([0, width - margin.right]);

const zx = xScale.copy();
const yScale = d3.scaleBand()
.domain(data.map(d => d[yKey]))
.range([0, height - margin.bottom])
.padding(0.1);

const xAxis = (g, scale) => {
console.log('in xAxis ' + scale.domain() + ' and range ' + scale.range());
g
.attr("class", "xAxis")
.call(d3.axisTop(scale).tickSizeOuter(0))
.call(g => g.select(".domain").remove());
};

const yAxis = (g, scale) => {
g
.attr("class", "yAxis")
.call(d3.axisLeft(scale))
.call(g => g.select(".domain").remove());
};
const gx = topContainer
.append("g")
.call(xAxis, zx);

const gy = topContainer
.append("g")
.call(yAxis, yScale);
const renderChart = (data) => {
topContainer
.selectAll("rect")
.data(data, d => d.key)
.enter()
.append("rect")
.attr("fill", "steelblue")
.attr("x", d => zx(0))
.attr("y", d => yScale(d[yKey]))
.attr("height", yScale.bandwidth());

const allRect = topContainer
.selectAll("rect");
if (animate) {
allRect
.transition()
.duration(1500)
.attr("width", d => zx(d[xKey]))
} else {
allRect
.attr("width", d => zx(d[xKey]));
}
topContainer
.selectAll(".barText")
.data(data, d => d.key)
.enter()
.append("text")
.attr("class", "barText")
.attr("y", d => yScale(d[yKey]) + (yScale.bandwidth()/2) + 4)
.attr("fill", "white")
.style("text-anchor", "end")
.each(function(d) {
const deepCopy = JSON.parse(JSON.stringify(d));
deepCopy[xKey] = 0;
this._current = deepCopy;
});

const allText = topContainer
.selectAll(".barText");
if (animate) {
allText
.transition()
.duration(1500)
.attr("x", d => zx(d[xKey])-5)
.textTween(function(d) {
const interpolateToD = d3.interpolate(this._current, d);
return (t) => {
this._current = interpolateToD(t);
return this._current[xKey].toFixed(0);
};
});
} else {
allText
.attr("x", d => zx(d[xKey]) - 5)
.text(d => d[xKey]);
}
}

renderChart(data);

return Object.assign(svg.node(), {
update(data) {
const t = svg.transition().duration(1000);
const newXDomain = [0, d3.max(data, d => d[xKey])];
zx.domain(newXDomain);
gx.transition(t).call(xAxis, zx);

renderChart(data);
}
});
}

Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more