diff --git a/plots/area-elevation-profile/implementations/javascript/echarts.js b/plots/area-elevation-profile/implementations/javascript/echarts.js new file mode 100644 index 0000000000..1c3f143cae --- /dev/null +++ b/plots/area-elevation-profile/implementations/javascript/echarts.js @@ -0,0 +1,180 @@ +// anyplot.ai +// area-elevation-profile: Terrain Elevation Profile Along Transect +// Library: echarts 5.5.1 | JavaScript 22.22.3 +// Quality: 88/100 | Created: 2026-06-10 + +//# anyplot-orientation: landscape + +const t = window.ANYPLOT_TOKENS; + +// --- Data ------------------------------------------------------------------- +// Control points [distance_km, elevation_m] — deterministic Alpine traverse +const ctrl = [ + [0, 780], [5, 1150], [10, 1820], [13, 2280], [17, 1450], + [21, 1320], [25, 1680], [30, 2050], [36, 2840], [40, 2450], + [44, 2190], [48, 2380], [52, 2560], [57, 1940], [62, 1480], + [66, 1100], [70, 900], [74, 780], [80, 650] +]; + +// 161 profile points at 0.5 km intervals: linear interp + micro-terrain texture +const profileData = []; +for (let i = 0; i <= 160; i++) { + const d = i * 0.5; + let base = ctrl[ctrl.length - 1][1]; + for (let j = 0; j < ctrl.length - 1; j++) { + if (d >= ctrl[j][0] && d <= ctrl[j + 1][0]) { + const frac = (d - ctrl[j][0]) / (ctrl[j + 1][0] - ctrl[j][0]); + base = ctrl[j][1] + frac * (ctrl[j + 1][1] - ctrl[j][1]); + break; + } + } + // Superimposed sinusoids add deterministic micro-terrain texture + const tex = 32 * Math.sin(d * 1.8 + 0.4) + 18 * Math.sin(d * 4.7 + 1.1) + + 9 * Math.sin(d * 10.3 + 2.3) + 5 * Math.sin(d * 19.1); + profileData.push([d, Math.round(base + tex)]); +} + +// Key landmarks along the traverse +const landmarks = [ + { name: 'Northern Pass · 2280 m', dist: 13 }, + { name: 'Valley Village · 1320 m', dist: 21 }, + { name: 'Main Summit · 2840 m', dist: 36 }, + { name: 'Plateau Hut · 2190 m', dist: 44 }, + { name: 'Eastern Pass · 2560 m', dist: 52 }, + { name: 'River Crossing · 900 m', dist: 70 }, +]; + +// --- Init ------------------------------------------------------------------- +const chart = echarts.init(document.getElementById('container')); + +// Terrain silhouette fill — Imprint green fading to transparent +const areaFill = { + type: 'linear', x: 0, y: 0, x2: 0, y2: 1, + colorStops: [ + { offset: 0, color: 'rgba(0,158,115,0.55)' }, + { offset: 1, color: 'rgba(0,158,115,0.04)' } + ] +}; + +// Scale title font for long string (default 22 px, floor 13 px) +const titleStr = 'Alpine Mountain Traverse · area-elevation-profile · javascript · echarts · anyplot.ai'; +const titleSize = Math.max(13, Math.round(22 * 67 / titleStr.length)); + +// --- Option ----------------------------------------------------------------- +chart.setOption({ + animation: false, + color: t.palette, + backgroundColor: 'transparent', + + title: { + text: titleStr, + subtext: '~16× vertical exaggeration', + subtextStyle: { color: t.inkSoft, fontSize: 12 }, + left: 'center', + top: 18, + textStyle: { color: t.ink, fontSize: titleSize, fontWeight: '500' } + }, + + grid: { left: 110, right: 55, top: 100, bottom: 90 }, + + xAxis: { + type: 'value', + min: 0, + max: 80, + name: 'Distance (km)', + nameLocation: 'middle', + nameGap: 50, + nameTextStyle: { color: t.inkSoft, fontSize: 14 }, + axisLabel: { color: t.inkSoft, fontSize: 13, formatter: '{value} km' }, + axisLine: { lineStyle: { color: t.inkSoft } }, + axisTick: { lineStyle: { color: t.inkSoft } }, + splitLine: { show: false } + }, + + yAxis: { + type: 'value', + min: 400, + name: 'Elevation (m)', + nameLocation: 'middle', + nameGap: 72, + nameTextStyle: { color: t.inkSoft, fontSize: 14 }, + axisLabel: { color: t.inkSoft, fontSize: 13, formatter: '{value} m' }, + axisLine: { show: false }, + axisTick: { show: false }, + splitLine: { lineStyle: { color: t.grid } } + }, + + series: [ + // Main elevation profile: filled terrain silhouette + annotated landmarks + { + type: 'line', + data: profileData, + smooth: 0.3, + symbol: 'none', + lineStyle: { color: t.palette[0], width: 2.5 }, + areaStyle: { color: areaFill }, + // Vertical dashed lines at landmark positions + markLine: { + silent: true, + symbol: ['none', 'none'], + lineStyle: { color: t.inkSoft, type: 'dashed', width: 1.3, opacity: 0.6 }, + label: { show: false }, + data: landmarks.map(lm => [ + { coord: [lm.dist, 420] }, + { coord: [lm.dist, profileData[Math.min(Math.round(lm.dist / 0.5), 160)][1] - 40] } + ]) + } + }, + // Landmark dots with labels above the profile line + { + type: 'scatter', + data: landmarks.map(lm => ({ + name: lm.name, + value: [lm.dist, profileData[Math.min(Math.round(lm.dist / 0.5), 160)][1] + 80] + })), + symbol: 'circle', + symbolSize: 5, + itemStyle: { color: t.inkSoft, opacity: 0.7 }, + label: { + show: true, + position: 'top', + formatter: '{b}', + color: t.ink, + fontSize: 13 + }, + z: 10 + }, + // Trailhead start marker + { + type: 'scatter', + data: [[0, profileData[0][1]]], + symbol: 'circle', + symbolSize: 12, + itemStyle: { color: t.palette[0], borderColor: t.ink, borderWidth: 2 }, + label: { + show: true, + position: 'right', + formatter: 'Trailhead · 780 m', + color: t.ink, + fontSize: 12 + }, + z: 10 + }, + // Mountain Town end marker + { + type: 'scatter', + data: [[80, profileData[160][1]]], + symbol: 'circle', + symbolSize: 12, + itemStyle: { color: t.palette[0], borderColor: t.ink, borderWidth: 2 }, + label: { + show: true, + position: 'left', + formatter: 'Mountain Town · 650 m', + color: t.ink, + fontSize: 12 + }, + z: 10 + } + ] +}); diff --git a/plots/area-elevation-profile/metadata/javascript/echarts.yaml b/plots/area-elevation-profile/metadata/javascript/echarts.yaml new file mode 100644 index 0000000000..a5b51fe945 --- /dev/null +++ b/plots/area-elevation-profile/metadata/javascript/echarts.yaml @@ -0,0 +1,274 @@ +library: echarts +language: javascript +specification_id: area-elevation-profile +created: '2026-06-10T06:13:08Z' +updated: '2026-06-10T06:33:25Z' +generated_by: claude-sonnet +workflow_run: 27256533741 +issue: 4578 +language_version: 22.22.3 +library_version: 5.5.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/area-elevation-profile/javascript/echarts/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/area-elevation-profile/javascript/echarts/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/area-elevation-profile/javascript/echarts/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/area-elevation-profile/javascript/echarts/plot-dark.html +quality_score: 88 +review: + strengths: + - Deterministic data generation using linear interpolation between hard-coded Alpine + control points plus superimposed sinusoidal terrain texture — elegant and fully + reproducible + - Gradient area fill (brand green 0.55 → transparent 0.04) creates a convincing + terrain silhouette that immediately conveys the mountain profile character + - ECharts markLine with explicit coordinate pairs draws vertical dashed lines precisely + from y=420 to just below the terrain line — idiomatic and accurate + - Title fontsize correctly scaled by formula (Math.max(13, round(22*67/titleLen))) + so the long descriptive prefix fits without overflow + - ~16× vertical exaggeration is noted in the subtitle, and the actual ratio is correctly + computed (~15.2× actual from grid dimensions) + - Theme-adaptive chrome uses all correct tokens (t.ink, t.inkSoft, t.grid, t.palette[0]) + throughout — both renders pass the readability check + - Start and end landmarks (Trailhead 780 m / Mountain Town 650 m) clearly labeled + with position:'right' / position:'left', fulfilling spec requirement + weaknesses: + - Landmark scatter dots use symbolSize:5 (5 CSS px = 10 native px at 2× DPR) — very + small at full resolution and barely visible at mobile scale (~400 px); increase + to symbolSize:9 or 10 for better visibility + - 'Some label crowding between adjacent landmarks: Valley Village (dist=21) and + Northern Pass (dist=13) labels are horizontally close on a descent segment; consider + staggering label vertical offsets to prevent near-collision in dense sections' + - Plateau Hut and surrounding labels appear within the green silhouette fill on + the ascending eastern slope (elevation ~2190 m, fill opacity 0.45–0.55 at that + height); the dark ink text remains readable but visually noisy — place dots higher + (+120 m offset instead of +80 m) to clear the silhouette top + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct, no pure white. + Chrome: Title "Alpine Mountain Traverse · area-elevation-profile · javascript · echarts · anyplot.ai" at scaled fontSize ~17px is fully visible and fits comfortably (~80% width). Subtitle "~16× vertical exaggeration" readable below title. Y-axis label "Elevation (m)" and X-axis label "Distance (km)" both visible in inkSoft color. Tick labels ("0 km"…"80 km", "500 m"…"3,000 m") clearly readable. All text is dark-on-light — no legibility failures. + Data: Brand green (#009E73) fills the terrain silhouette from the profile line down to y=400 m with a gradient (0.55 opacity at top → 0.04 at bottom), creating a convincing Alpine terrain silhouette. Six landmark dashed vertical lines and labels (Northern Pass · 2280 m, Valley Village · 1320 m, Main Summit · 2840 m, Plateau Hut · 2490 m, Eastern Pass · 2560 m, River Crossing · 900 m) are visible above the profile. Start (Trailhead · 780 m) and end (Mountain Town · 650 m) markers are green dots with dark borders and legible inline labels. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct, not pure black. + Chrome: Title, subtitle, axis labels, and tick labels all rendered in light ink (#F0EFE8 / #B8B7B0) — clearly readable against the dark surface. No dark-on-dark failures observed. Grid lines subtle but visible. Brand green profile line and fill are identical in hue to the light render (data colors are theme-independent as required). + Data: Same brand green terrain silhouette; fill slightly more visible against the dark background, creating a strong visual effect. All landmark labels and endpoint labels retain correct ink color and are fully legible. No "dark-on-dark" text detected. + Legibility verdict: PASS + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: 'All font sizes explicitly set (title scaled by formula, axis/tick/label + sizes specified). Readable in both themes at full resolution. Minor: landmark + labels at fontSize:13 are slightly small at mobile scale.' + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: 'No severe overlap. Minor crowding: Valley Village (dist=21) and + Northern Pass (dist=13) labels are close on the descent segment. Plateau + Hut label appears partially within the silhouette fill but text remains + readable with high contrast.' + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: Terrain silhouette fill, profile line, endpoint markers, and landmark + labels all clearly visible. Gradient fill creates effective terrain silhouette. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Single-series with brand green — CVD-safe. Dark ink labels against + light/tinted surfaces maintain high contrast ratios. + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas gate passed. Grid margins (left:110, right:55, top:100, bottom:90) + give generous whitespace. No canvas-gate failure. No AR-09 clipping detected. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: 'X: ''Distance (km)'', Y: ''Elevation (m)'' — both descriptive with + units.' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: First series uses t.palette[0] (#009E73). Gradient fill uses rgba(0,158,115,...) + — same hue. Background transparent (shows page bg). All chrome tokens (t.ink, + t.inkSoft, t.grid) used correctly in both themes. + design_excellence: + score: 13 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Above defaults: gradient terrain fill, landmark annotations, custom + title prefix, vertical dashed guidelines. Intentional design hierarchy. + Not publication-quality (FiveThirtyEight level) but clearly above a configured + default.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Y-axis line hidden, y-axis ticks hidden, x-axis splitLine disabled, + only subtle horizontal grid lines, transparent background. Clear visual + refinement above library defaults. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: 'Strong terrain narrative: silhouette conveys mountain journey, labeled + landmarks provide waypoints, Main Summit at 2840 m is clear focal point. + Vertical exaggeration annotated for context. Good visual hierarchy.' + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Area-elevation profile with filled terrain silhouette — correct chart + type. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: 'All spec features present: gradient fill below profile, start/end + labels with elevations, 6 landmark annotations with vertical marker lines, + vertical exaggeration noted (~16×).' + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X = distance (km), Y = elevation (m). Axes display full 0–80 km range + and 400–3000+ m range. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: 'Title: ''Alpine Mountain Traverse · area-elevation-profile · javascript + · echarts · anyplot.ai'' — correct {Descriptive} · {spec-id} · {lang} · + {lib} · anyplot.ai format. Single series, no legend required.' + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 161 sample points at 0.5 km resolution with ascents, descents, passes, + summits, valleys, and river crossing — full feature coverage of the elevation + profile type. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Alpine traverse with realistic elevation (650–2840 m), 80 km length, + plausible landmarks (passes, summit, hut, river crossing). Neutral outdoor + scenario. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Elevation range 650–2840 m appropriate for Alpine terrain. 80 km + traverse is realistic for multi-day hike. Control points produce geomorphologically + plausible ridge-valley profile. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Linear flow: data → init → option. No functions or classes.' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: 'Fully deterministic: hard-coded control points + deterministic sinusoidal + texture functions.' + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: No imports (ECharts is a global). All globals used (t, chart). + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean code, appropriate complexity. No over-engineering. No fake + UI. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: ECharts harness saves plot-{THEME}.png and plot-{THEME}.html correctly. + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: Correct animation:false, no explicit dimensions, line+areaStyle, + markLine, scatter series composition, smooth parameter — all idiomatic ECharts + patterns used correctly. + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses markLine with explicit coord pairs (ECharts-specific), linear + gradient areaStyle (ECharts gradient API), multi-series z-ordering — features + that leverage ECharts specifically. + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - annotations + - html-export + patterns: + - data-generation + - iteration-over-groups + dataprep: + - interpolation + styling: + - gradient-fill + - alpha-blending