Public
Edited
Oct 15, 2023
1 fork
5 stars
Insert cell
Insert cell
Insert cell
chart2 = {
const strokeWidth = 2;
const padding = strokeWidth + 3;
const numRows = myLanguagesByLevel.length;
const w = 640;
const h = 290;
const rowHeight = (h - padding * (numRows - 1) - strokeWidth) / numRows;
const leftMargin = 30;

const svg = d3.select(DOM.svg(w, h));

const rows = svg
.selectAll("g")
.data(myLanguagesByLevel)
.join("g")
.attr(
"transform",
(d, i) =>
`translate(${[
strokeWidth / 2 + leftMargin,
i * (rowHeight + padding) + strokeWidth / 2
]})`
)
.each(function ([level, languages]) {
const numCols = languages.length;
const colWidth =
(w - strokeWidth - padding * (numCols - 1) - leftMargin) / numCols;

const g = d3
.select(this)
.selectAll("g")
.data(languages)
.join("g")
.attr(
"transform",
(d, i) => `translate(${[i * (colWidth + padding), 0]})`
);

g.append("rect")
.attr("fill", "transparent")
// .attr("fill", "lightblue")
.attr("opacity", .3)

.attr("stroke", "black")
// .attr("stroke-width", strokeWidth)
.attr("height", rowHeight)
.attr("width", colWidth);

// g.append("text")
// .attr("text-anchor", "middle")
// .attr("transform", `translate(${[colWidth / 2, rowHeight / 2]})`)
// .attr("dy", ".35em")
// .text((d) => d)
// .attr("fill", "black");

// Flags
// g.append("g")
// .attr("transform", `translate(${[strokeWidth / 2, strokeWidth / 2]})`) // you can't transform a nested svg
// .append((language) => getFlag(language))
// .attr("preserveAspectRatio", "xMidYMid meet")
// .attr("width", colWidth - strokeWidth)
// .attr("height", rowHeight - strokeWidth);
// // .attr("preserveAspectRatio", "none") // stretch the flags (looks hideous)

// Wordclouds
g.append("g")
// .attr("transform", `translate(${[strokeWidth / 2, strokeWidth / 2]})`) // you can't transform a nested svg
.append((language) =>
WordCloud({
width: colWidth - padding,
height: rowHeight - padding,
padding: 1,
rotate: 0,
fontScale: 5,
fontFamily: "Monaco",
language,
spiral: "rectangular"
})
)
.attr("width", colWidth - strokeWidth)
.attr("height", rowHeight - strokeWidth);
});

rows.each(function ([level, languages]) {
d3.select(this)
.append("text")
.text(level)
.attr("font-family", "Impact")
.attr("font-size", 40)
.attr("opacity", .3)
.attr(
"transform",
(d, i) => `translate(${[-leftMargin, rowHeight/2]})`
)
.attr('dy', 15);
});

return svg.node();
}
Insert cell
// see https://github.com/hampusborgos/country-flags/blob/main/countries.json
myLanguages = [
{ language: "es", level: "N" },
{ language: "en", level: "C" },
{ language: "it", level: "C" },
{ language: "fr", level: "B" },
{ language: "pt", level: "B" },
{ language: "ca", level: "B" },
{ language: "de", level: "A" },
// { language: "he", level: "A" },
{ language: "po", level: "A" },
// { language: "ar", level: "A" },
]
Insert cell
languageInfo = ({
es: {flag: "ES", name: "español"},
en: {flag: "US", name: "English"},
it: {flag: "IT", name: "italiano"},
fr: {flag: "FR", name: "français"},
pt: {flag: "PT", name: "português"},
ca: {flag: "CA", name: "catalá"}, // TODO: fix flag
he: {flag: "IL", name: "עברית"},
de: {flag: "DE", name: "Deutsch"},
po: {flag: "PL", name: "polska"},
ar: {flag: "MA", name: "لعربية"}
})
Insert cell
getFlag = (language) => flags.get(languageInfo[language].flag).cloneNode(true);
Insert cell
myLanguagesByLevel = d3
.groups(myLanguages, (d) => d.level)
.map(([level, d]) => [level, d.map(({ _, language }) => language)])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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