Public
Edited
Dec 30, 2023
Fork of Ratings 2023
1 fork
Insert cell
md`# Flags 2023`
Insert cell
Insert cell
Insert cell
flag = (country_code) => {
switch (country_code) {
case "ru":
return `${country_code} 🇷🇺`;
case "ua":
return `${country_code} 🇺🇦`;
case "us":
return `${country_code} 🇺🇸`;
case "de":
return `${country_code} 🇩🇪`;
case "by":
return `${country_code} 🇧🇾`;
case "ca":
return `${country_code} 🇨🇦`;
case "nl":
return `${country_code} 🇳🇱`;
case "il":
return `${country_code} 🇮🇱`;
case "gb":
return `${country_code} 🇬🇧`;
case "lv":
return `${country_code} 🇱🇻`;
case "fr":
return `${country_code} 🇫🇷`;
case "cz":
return `${country_code} 🇨🇿`;
case "kz":
return `${country_code} 🇰🇿`;
case "md":
return `${country_code} 🇲🇩`;
case "ar":
return `${country_code} 🇦🇷`;
default:
return country_code;
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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);

// return

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();
}
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