chart = {
const height = 500;
const svg = d3.select(DOM.svg(width, height));
const margin = {
top: 60,
right: 0,
bottom: 5,
left: 80
};
const barPadding =
(height - (margin.bottom + margin.top)) / ((topCount + 1) * 5);
const title = svg
.append("text")
.attr("class", "title")
.attr("y", 24)
.html("Количество комментариев d3.ru по странам");
const months = Object.keys(counts).sort();
const next = (index) => {
return index >= months.length ? null : counts[months[index]].top;
};
let index = 0;
let slice = next(index);
let x = d3
.scaleLinear()
.domain([0, d3.max(counts[months[index]].top, (d) => d.count)])
.range([margin.left, width - margin.right - 65]);
let y = d3
.scaleLinear()
.domain([topCount + 1, 0])
.range([height - margin.bottom, margin.top]);
let xAxis = d3
.axisTop()
.scale(x)
.ticks(width > 500 ? 5 : 2)
.tickSize(-(height - margin.top - margin.bottom))
.tickFormat((d) => d3.format(",")(d));
svg
.append("g")
.attr("class", "axis xAxis")
.attr("transform", `translate(0, ${margin.top})`)
.call(xAxis)
.selectAll(".tick line")
.classed("origin", (d) => d == 0);
svg
.selectAll("rect.bar")
.data(slice, (d) => d.country_code)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", x(0) + 1)
.attr("width", (d) => x(d.count) - x(0) - 1)
.attr("y", (d) => y(d.rank) + 5)
.attr("height", y(1) - y(0) - barPadding)
.style("fill", "#f7da72CC");
svg
.selectAll("text.label")
.data(slice, (d) => d.country_code)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (d) => x(d.count) - 8)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1)
.attr("text-anchor", "end")
.html((d) => d.country_code);
svg
.selectAll("text.valueLabel")
.data(slice, (d) => d.country_code)
.enter()
.append("text")
.attr("class", "valueLabel")
.attr("x", (d) => x(d.count) + 5)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1)
.text((d) => d3.format(",.0f")(d.count));
let yearText = svg
.append("text")
.attr("class", "yearText")
.attr("x", width - margin.right)
.attr("y", height - 40)
.style("text-anchor", "end")
.html(months[index].replace("-", "."))
.call(halo, 10);
let ticker = d3.interval((e) => {
slice = next(index++);
if (slice === null) ticker.stop();
x.domain([0, d3.max(slice, (d) => d.count)]);
svg
.select(".xAxis")
.transition()
.duration(duration)
.ease(d3.easeLinear)
.call(xAxis);
let bars = svg.selectAll(".bar").data(slice, (d) => d.country_code);
bars
.enter()
.append("rect")
.attr("class", (d) => `bar ${d.country_code.replace(/\s/g, "_")}`)
.attr("x", x(0) + 1)
.attr("width", (d) => x(d.count) - x(0) - 1)
.attr("y", (d) => y(topCount + 2) + 5)
.attr("height", y(1) - y(0) - barPadding)
.style("fill", "#f7da72CC")
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("y", (d) => y(d.rank) + 5);
bars
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("width", (d) => x(d.count) - x(0) - 1)
.attr("y", (d) => y(d.rank) + 5);
bars
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attr("width", (d) => x(d.count) - x(0) - 1)
.attr("y", (d) => y(topCount + 2) + 5)
.remove();
let labels = svg.selectAll(".label").data(slice, (d) => d.country_code);
labels
.enter()
.append("text")
.attr("class", "label")
.attr("x", (d) => x(d.count) - 8)
.attr("y", (d) => y(topCount + 2) + 5 + (y(1) - y(0)) / 2)
.attr("text-anchor", "end")
.html((d) => d.country_code)
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1);
labels
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("x", (d) => x(d.count) - 8)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1);
labels
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attr("x", (d) => x(d.count) - 8)
.attr("y", (d) => y(topCount + 2) + 5)
.remove();
let valueLabels = svg
.selectAll(".valueLabel")
.data(slice, (d) => d.country_code);
valueLabels
.enter()
.append("text")
.attr("class", "valueLabel")
.attr("x", (d) => x(d.count) + 5)
.attr("y", (d) => y(topCount + 2) + 5)
.text((d) => d3.format(",.0f")(d.count))
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1);
valueLabels
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr("x", (d) => x(d.count) + 5)
.attr("y", (d) => y(d.rank) + 5 + (y(1) - y(0)) / 2 + 1)
.tween("text", function (d) {
const previous = counts[months[Math.max(0, index - 2)]].all.find(
(x) => x.domain === d.country_code
);
let previousRating = 0;
if (previous) {
previousRating = previous.count;
}
debugger;
let i = d3.interpolateRound(previousRating, d.count);
return function (t) {
this.textContent = d3.format(",")(i(t));
};
});
valueLabels
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attr("x", (d) => x(d.count) + 5)
.attr("y", (d) => y(topCount + 2) + 5)
.remove();
yearText.html(months[index].replace("-", "."));
}, duration);
return svg.node();
}