chart = {
{
const style = document.createElement("style");
style.textContent = `
@font-face {
font-family: 'Elastre';
src: url('https://res.cloudinary.com/dtu3vkxv6/raw/upload/v1746886734/Elastre_HEXP_INKT_vfwhma.ttf') format('truetype');
}
label, input[type="range"], span {
font-family: 'Elastre', sans-serif !important;
font-size: 10px;
}
`;
document.head.appendChild(style);
}
const series = d3.rollup(transformed, v => d3.sort(v, d => d.date), d => d.name);
const marginTop = 30;
const marginRight = 10;
const marginBottom = 0;
const marginLeft = 100;
const width = 928;
const size = 25;
const height = series.size * size + marginTop + marginBottom;
const padding = 1;
const x = d3.scaleUtc()
.domain(d3.extent(transformed, d => d.date))
.range([0, width - marginLeft - marginRight]);
const y = d3.scaleLinear()
.domain([0, d3.max(transformed, d => d.value)])
.range([size, size - bands * (size - padding)]);
const area = d3.area()
.defined(d => !isNaN(d.value))
.x(d => x(d.date))
.y0(size)
.y1(d => y(d.value));
const uid = `O-${Math.random().toString(16).slice(2)}`;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; font-size: 8px; font-family: Elastre, sans-serif;");
// ✅ 添加字体样式到 SVG <style>
svg.append("style").text(`
@font-face {
font-family: 'Elastre';
src: url('https://res.cloudinary.com/dtu3vkxv6/raw/upload/v1746886734/Elastre_HEXP_INKT_vfwhma.ttf') format('truetype');
}
`);
const g = svg.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("transform", (d, i) => `translate(0,${i * size + marginTop})`);
const defs = g.append("defs");
defs.append("clipPath")
.attr("id", (_, i) => `${uid}-clip-${i}`)
.append("rect")
.attr("x", marginLeft)
.attr("y", padding)
.attr("width", width - marginLeft - marginRight)
.attr("height", size - padding);
defs.append("path")
.attr("id", ([, values], i) => `${uid}-path-${i}`)
.attr("d", ([, values]) => area(values));
g.append("g")
.attr("clip-path", (_, i) => `url(#${uid}-clip-${i})`)
.selectAll("use")
.data((_, i) => new Array(bands).fill(i))
.enter().append("use")
.attr("xlink:href", i => `#${uid}-path-${i}`)
.attr("fill", (_, i) => colors[i % colors.length])
.attr("transform", (_, i) => `translate(${marginLeft},${i * size})`);
g.append("text")
.attr("x", 4)
.attr("y", (size + padding) / 2)
.attr("dy", "0.35em")
.text(([name]) => name);
svg.append("g")
.attr("transform", `translate(${marginLeft},${marginTop})`)
.call(d3.axisTop(x).ticks(width / 80).tickSizeOuter(0))
.call(g => g.selectAll(".tick")
.filter(d => x(d) < 0 || x(d) >= width - marginLeft - marginRight)
.remove())
.call(g => g.select(".domain").remove());
svg.selectAll(".tick text")
.style("font-family", "Elastre")
.style("font-size", "8px");
return svg.node();
}