Spaces:
Sleeping
Sleeping
| """Area chart template — fetch-and-adapt from d3-graph-gallery.com. | |
| Adapted from d3-graph-gallery.com (Yan Holtz) — | |
| https://d3-graph-gallery.com/graph/area_basic.html | |
| """ | |
| from __future__ import annotations | |
| from pydantic import BaseModel | |
| from app.agents.d3.registry import D3Template, register | |
| class Point(BaseModel): | |
| x: float | |
| y: float | |
| class AreaData(BaseModel): | |
| title: str = "" | |
| x_label: str = "" | |
| y_label: str = "" | |
| data: list[Point] | |
| _HTML = """<!-- Adapted from d3-graph-gallery.com (Yan Holtz) — https://d3-graph-gallery.com/graph/area_basic.html --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://d3js.org/d3.v7.min.js"></script> | |
| <style> | |
| html, body { margin: 0; padding: 0; width: 100vw; height: 100vh; background: #FAF7F2; color: #1A3557; font-family: Georgia, 'Libre Caslon Text', serif; overflow: hidden; } | |
| #my_dataviz { width: 100vw; height: 100vh; } | |
| .axis text { fill: #1A3557; font-size: 12px; } | |
| .axis path, .axis line { stroke: #1A3557; } | |
| .chart-title { fill: #1A3557; font-size: 18px; text-anchor: middle; } | |
| .axis-label { fill: #1A3557; font-size: 13px; text-anchor: middle; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="my_dataviz"></div> | |
| <script> | |
| const data = __DATA__; | |
| // set the dimensions and margins of the graph | |
| const margin = {top: 50, right: 30, bottom: 60, left: 60}, | |
| width = 960 - margin.left - margin.right, | |
| height = 600 - margin.top - margin.bottom; | |
| // append the svg object to the body of the page | |
| const svg = d3.select("#my_dataviz") | |
| .append("svg") | |
| .attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`) | |
| .attr("preserveAspectRatio", "xMidYMid meet") | |
| .style("width", "100%") | |
| .style("height", "100%") | |
| .append("g") | |
| .attr("transform", `translate(${margin.left},${margin.top})`); | |
| // Chart title | |
| svg.append("text") | |
| .attr("class", "chart-title") | |
| .attr("x", width / 2) | |
| .attr("y", -20) | |
| .text(data.title); | |
| // Add X axis | |
| const x = d3.scaleLinear() | |
| .domain(d3.extent(data.data, d => d.x)) | |
| .range([ 0, width ]); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .attr("transform", `translate(0, ${height})`) | |
| .call(d3.axisBottom(x)); | |
| svg.append("text") | |
| .attr("class", "axis-label") | |
| .attr("x", width / 2) | |
| .attr("y", height + margin.bottom - 10) | |
| .text(data.x_label); | |
| // Add Y axis | |
| const y = d3.scaleLinear() | |
| .domain([0, d3.max(data.data, d => d.y)]) | |
| .range([ height, 0 ]); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .call(d3.axisLeft(y)); | |
| svg.append("text") | |
| .attr("class", "axis-label") | |
| .attr("transform", "rotate(-90)") | |
| .attr("x", -height / 2) | |
| .attr("y", -45) | |
| .text(data.y_label); | |
| // Add the area | |
| svg.append("path") | |
| .datum(data.data) | |
| .attr("fill", "#4A7FB5") | |
| .attr("fill-opacity", 0.4) | |
| .attr("stroke", "#4A7FB5") | |
| .attr("stroke-width", 2) | |
| .attr("d", d3.area() | |
| .x(d => x(d.x)) | |
| .y0(y(0)) | |
| .y1(d => y(d.y)) | |
| ); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| golden_sample = AreaData( | |
| title="Demo", | |
| x_label="Time", | |
| y_label="Value", | |
| data=[Point(x=0, y=1), Point(x=1, y=3), Point(x=2, y=2)], | |
| ) | |
| register( | |
| D3Template( | |
| id="area", | |
| family="chart", | |
| title="Area chart", | |
| when_to_use="Show a single numeric value's magnitude changing over an ordered/continuous axis, emphasizing volume under the curve.", | |
| data_requirements="A sequence of (x, y) points, ordered along x.", | |
| schema=AreaData, | |
| html_template=_HTML, | |
| golden_sample=golden_sample, | |
| ) | |
| ) | |