Hand-drawn pie chart (mlcrough renderer API)
Drives the `mlcrough` engine extension via Engine.getMlcrough(). The user script computes each slice's path and feeds it to the renderer's .path() method with `multi-hachure` fill — every slice is independently sketched. The exploded slice is offset radially. Labels via raw SVG <text> with stroke-paint for legibility.
Hand-drawn pie chart
JavaScript
// Hand-drawn pie chart via Engine.getMlcrough().
// demo_rough_piechart.js
//!NOIMAGE
//!OUTPUT: OUTPUT
//!PARAM: WIDTH:integer=600,min=300,max=1200
//!PARAM: HEIGHT:integer=600,min=300,max=1200
//!PARAM: SCALE:number=2,min=1,max=4,step=0.5
const r = Engine.getMlcrough({
width: WIDTH, height: HEIGHT, background: "#f8f9fa",
});
const data = [
{ label: "A", value: 30, color: "#e74c3c" },
{ label: "B", value: 50, color: "#3498db", highlight: true },
{ label: "C", value: 20, color: "#2ecc71" },
{ label: "D", value: 40, color: "#f1c40f" },
];
const cx = WIDTH / 2;
const cy = HEIGHT / 2;
const radius = Math.min(WIDTH, HEIGHT) * 0.36;
const total = data.reduce((s, d) => s + d.value, 0);
let start = -Math.PI / 2;
data.forEach(d => {
const slice = (d.value / total) * 2 * Math.PI;
const end = start + slice;
// Exploded slice — offset the centre.
let x = cx, y = cy;
if (d.highlight) {
const mid = start + slice / 2;
x += Math.cos(mid) * 20;
y += Math.sin(mid) * 20;
}
const x1 = x + Math.cos(start) * radius;
const y1 = y + Math.sin(start) * radius;
const x2 = x + Math.cos(end) * radius;
const y2 = y + Math.sin(end) * radius;
const largeArc = slice > Math.PI ? 1 : 0;
r.path(
`M ${x} ${y} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} Z`,
{ fill: d.color, fillStyle: "multi-hachure", hachureAngle: 45, hachureGap: 5 },
);
// Label inside the slice.
const labA = start + slice / 2;
const lr = radius * 0.7;
r.raw(`<text x="${x + Math.cos(labA) * lr}" y="${y + Math.sin(labA) * lr}" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="16" font-weight="bold" fill="#fff" stroke="#000" stroke-width="0.5" paint-order="stroke">${d.label}</text>`);
start = end;
});
r.toImage(SCALE).save(OUTPUT);
// © 2026 Michael Lechner · mlc OpticScript · https://mlcgo.eu · Elastic License 2.0