Published
Edited
Mar 22, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dataRing1 = [
{
text: "Test 1",
startAngle: 0,
endAngle: 60,
fontSize: 14,
letterSpace: 1
},
{
text: "TEST 1",
startAngle: 60,
endAngle: 180,
fontSize: 40,
letterSpace: 2
},
{
text: "WHOUAOU ÇA MARCHE 1",
startAngle: 180,
endAngle: 360,
fontSize: 30,
letterSpace: 2
}
]
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.

ringObjHTML = (ring) => {
const {
cx,
cy,
r,
innerR,
padAngle = 1,
color = "red",
data, // contains : d.startAngle d.endAngle d.text d.fontSize=12 d.letterSpace=1 d.textOffAngle
// d.uid (d.index?) is created in this function
strokeWidth = 2, // 0 invert colors and fill up
bold = true
} = ring;

const halfPI = Math.PI / 2;
const svg = d3.create("svg");
const arc = d3
.arc()
.innerRadius(r)
.outerRadius(r + innerR)
.padAngle((Math.PI / 180) * padAngle)
.startAngle((d) => (Math.PI / 180) * d.startAngle)
.endAngle((d) => (Math.PI / 180) * d.endAngle);
const atBottom = (d) => {
const middle =
((Math.PI / 180) * d.startAngle -
halfPI +
(Math.PI / 180) * 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,
(Math.PI / 180) * d.endAngle - halfPI,
(Math.PI / 180) * d.startAngle - halfPI,
true
);
} else {
context.arc(
0,
0,
r,
(Math.PI / 180) * d.startAngle - halfPI,
(Math.PI / 180) * 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) ? +1.15 : -0.85))
.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.letterSpace
? d.text.split("").join("\xa0".repeat(d.letterSpace))
: d.text
);
};
data.forEach((d) => (d.uid = DOM.uid("p-" + d.index)));

svg.selectAll("g.arcLabel").data(data).join(enter);
return svg.node().innerHTML;
}
Insert cell
function darken(color, k = 1) {
const { l, c, h } = d3.lch(color);
return d3.lch(l - 30 * k, c, h);
}
Insert cell
myColor(12, 0, 6, 0.2)("test")
Insert cell
myColor(12, 0, 6, 0.2)("test")
Insert cell
// Function that give a scale of # (colorNum) according to rainbow. It can rotate the array, shuffle them with a seed or darken
// 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
);

const colorsDark = colors.map((color) => darken(color, dark).toString());
console.log("colors and colorsDark");
console.log(colors, colorsDark);
const colorsCopy = JSON.parse(JSON.stringify(colors));
const colorsCopyDark = JSON.parse(JSON.stringify(colorsDark));
console.log("colorsCopy and colorsCopyDark");
console.log(colorsCopy, colorsCopyDark);

console.log("colorsCopyShuffle and colorsCopyDarkShuffle");
console.log(
shuffleSeed.shuffle(colorsCopy, 2),
shuffleSeed.shuffle(colorsCopyDark, 2)
);
// 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);

// if (seed != false) {
// if (dark == false) {
// return d3.scaleOrdinal(shuffleSeed.shuffle(colorsCopyDark, seed));
// } else {
// return d3.scaleOrdinal(shuffleSeed.shuffle(colorsCopy, seed));
// }
// } else {
// if (dark != false) {
// return d3.scaleOrdinal(colorsDark);
// } else {
// return d3.scaleOrdinal(colors);
// }
// }

if (dark != false) {
// either true or is a number
if (seed != false) {
// either true or is a number
return d3.scaleOrdinal(shuffleSeed.shuffle(colorsCopyDark, seed));
} else {
//
return d3.scaleOrdinal(colorsCopyDark);
}
} else {
if (seed != false) {
// either true or is a number
return d3.scaleOrdinal(shuffleSeed.shuffle(colorsCopy, seed));
} else {
return d3.scaleOrdinal(colors);
}
}
}
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