Public
Edited
Oct 4, 2023
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);

const ring1 = ringHTML(
250, // cx
250, // cy
200, // r
25, // inner radius
1.2, // padding angle
myColor(12, ColorRotation, Shuffleseed), // colors
data, // see below how to organize data
2, // stroke width (2 by default), 0 makes it fill
true // bold (true by default)
);
svg.append("g").html(ring1);

const ring2 = ringHTML(
250,
250,
170,
50,
1.4,
myColor(3),
data2,
0,
true,
false // not working
);
svg.append("g").html(ring2);

const ring3 = ringHTML(250, 250, 115, 40, 3, myColor(3), data3, 3, true, 2);
svg.append("g").html(ring3);

return svg.node();
}
Insert cell
Insert cell
Insert cell
// Function that create a HTML layer arc of multile labels with options.
// data contains the angles, text, font-size & letter-spacing.

ringHTML = (
cx,
cy,
r,
innerR,
padAngle,
color,
data,
strokeWidth = 2, // 0 invert colors and fill up
bold = true
) => {
// d.startAngle d.endAngle d.data (text) d.fontsize=12 d.letterspacing=1

const halfPI = Math.PI / 2;

const svg = d3.create("svg");

const arc = d3
.arc()
.innerRadius(r - innerR)
.outerRadius(r)
.padAngle((Math.PI / 180) * padAngle);

const atBottom = (d) => {
const middle = (d.startAngle - halfPI + d.endAngle - halfPI) / 2;
return middle >= 0 && middle < Math.PI;
};

const enter = (enter) => {
const g = enter
.append("g")
.attr("class", "arcLabel")
.attr("transform", `translate(${cx}, ${cy})`);
g.append("path")
.attr("id", (d) => d.uid.id)
.style("fill", "none")
.attr("d", (d) => {
const context = d3.path();
if (atBottom(d)) {
context.arc(
0,
0,
r,
d.endAngle - halfPI,
d.startAngle - halfPI,
true
);
} else {
context.arc(
0,
0,
r,
d.startAngle - halfPI,
d.endAngle - halfPI,
false
);
}
return context.toString();
});
g.append("path")
.style("stroke", strokeWidth != 0 ? (d) => color(d.uid) : null)
.style("stroke-width", strokeWidth)
.style("fill", strokeWidth != 0 ? "transparent" : (d) => color(d.uid))
.attr("d", (d) => arc(d));
g.append("text")
.style("fill", strokeWidth != 0 ? (d) => color(d.uid) : "white")
.style("font-size", (d) => (d.fontSize ? d.fontSize : 12))
.style("font-weight", bold ? "bold" : "normal")
.attr("dy", (d) => (innerR / 2) * (atBottom(d) ? -0.9 : 1.15))
.attr("dominant-baseline", "middle")
.attr("text-anchor", "middle")
.append("textPath")
.attr("startOffset", "50%")
.attr("startOffset", (d) =>
d.textOffAngle ? 50 + d.textOffAngle + "%" : "50%"
)
.attr("xlink:href", (d) => d.uid.href)
.text((d) =>
d.space ? d.data.split("").join("\xa0".repeat(d.space)) : d.data
);
};
data.forEach((d) => (d.uid = DOM.uid("p-" + d.index)));

svg.selectAll("g.arcLabel").data(data).join(enter);
return svg.node().innerHTML;
}
Insert cell
myColor(2)("test")
Insert cell
// Function that give a scale of # (colorNum) according to rainbow. It can rotate the array or shuffle them with a seed

// shuffleSeed = require("https://bundle.run/shuffle-seed@1.1.6")

myColor = (colorNum, rotateNum = 0, seed = false, dark = false) => {
function darken(color, k = 1) {
const { l, c, h } = d3.lch(color);
return d3.lch(l - 30 * k, c, h);
}

const rotate = (arr, d) => {
for (let i = d; i < arr.length; i++) arr.unshift(arr.pop());
return arr;
};

const colors = rotate(
d3.quantize(d3.interpolateRainbow, colorNum + 1).slice(0, -1),
rotateNum
);

if (dark != false) colors = darken(colors, dark);

const colorsCopy = JSON.parse(JSON.stringify(colors));

// const shuffeledColors = colorsCopy.sort(() => { // old methode doesn't required shuffleSeed
// const randomTrueOrFalse = Math.random() > 0.5;
// return randomTrueOrFalse ? 1 : -1;
// });
// return shuffeled ? d3.scaleOrdinal(shuffeledColors) : d3.scaleOrdinal(colors);

return seed != false
? d3.scaleOrdinal(shuffleSeed.shuffle(colorsCopy, seed))
: d3.scaleOrdinal(colors);
}
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