diff --git a/plots/dumbbell-basic/implementations/javascript/echarts.js b/plots/dumbbell-basic/implementations/javascript/echarts.js new file mode 100644 index 0000000000..205465d77a --- /dev/null +++ b/plots/dumbbell-basic/implementations/javascript/echarts.js @@ -0,0 +1,152 @@ +// anyplot.ai +// dumbbell-basic: Basic Dumbbell Chart +// Library: echarts 5.5.1 | JavaScript 22.23.0 +// Quality: 93/100 | Created: 2026-06-30 +//# anyplot-orientation: landscape + +const tokens = window.ANYPLOT_TOKENS; + +// Department efficiency scores (0–100) before/after digital transformation +// Legal and Finance show slight decline; remaining departments all improved +// Sorted ascending by delta so largest gain appears at top (Y-axis bottom→top) +const departments = [ + "Legal", "Finance", "Operations", "HR", + "Logistics", "R&D", "Marketing", "IT", "Engineering", "Sales" +]; +const scoreBefore = [74, 73, 70, 61, 69, 64, 55, 67, 62, 58]; +const scoreAfter = [71, 70, 85, 78, 86, 83, 79, 91, 88, 84]; + +const deltas = departments.map(function(_, i) { return scoreAfter[i] - scoreBefore[i]; }); +const maxAbsDelta = Math.max.apply(null, deltas.map(Math.abs)); + +const chart = echarts.init(document.getElementById("container")); + +const titleText = + "Digital Transformation · dumbbell-basic · javascript · echarts · anyplot.ai"; +const titleFontSize = Math.round(22 * Math.min(1, 67 / titleText.length)); + +chart.setOption({ + animation: false, + color: tokens.palette, + backgroundColor: "transparent", + title: { + text: titleText, + left: "center", + top: 20, + textStyle: { color: tokens.ink, fontSize: titleFontSize, fontWeight: "500" } + }, + legend: { + data: [ + { name: "Before", icon: "circle", itemStyle: { color: tokens.palette[0] } }, + { name: "After", icon: "circle", itemStyle: { color: tokens.palette[1] } } + ], + top: 58, + left: "center", + itemGap: 32, + itemWidth: 14, + itemHeight: 14, + textStyle: { color: tokens.inkSoft, fontSize: 14 } + }, + tooltip: { + trigger: "item", + backgroundColor: tokens.elevatedBg, + borderColor: tokens.grid, + textStyle: { color: tokens.ink, fontSize: 13 }, + formatter: function(params) { + if (params.seriesType !== "scatter") return ""; + var idx = params.dataIndex; + var delta = deltas[idx]; + var sign = delta >= 0 ? "+" : ""; + return ( + "" + departments[idx] + "
" + + "Before: " + scoreBefore[idx] + "
" + + "After: " + scoreAfter[idx] + "
" + + "Change: " + sign + delta + ); + } + }, + grid: { left: 130, right: 90, top: 100, bottom: 70 }, + xAxis: { + type: "value", + min: 40, + max: 100, + name: "Efficiency Score", + nameLocation: "middle", + nameGap: 42, + nameTextStyle: { color: tokens.inkSoft, fontSize: 14 }, + axisLabel: { color: tokens.inkSoft, fontSize: 13 }, + axisLine: { show: false }, + axisTick: { show: false }, + splitLine: { show: false } + }, + yAxis: { + type: "category", + data: departments, + axisLabel: { color: tokens.inkSoft, fontSize: 13 }, + axisLine: { lineStyle: { color: tokens.inkSoft } }, + axisTick: { show: false }, + splitLine: { show: false } + }, + series: [ + // Connector lines: color encodes direction (inkSoft=gain / matte-red=decline), + // lineWidth and opacity scale with |delta| to visually rank the magnitude of change + { + type: "custom", + name: "_connector", + renderItem: function(params, api) { + var delta = deltas[params.dataIndex]; + var frac = Math.abs(delta) / maxAbsDelta; + var lineWidth = 1.5 + 3.5 * frac; + var opacity = 0.25 + 0.45 * frac; + var color = delta >= 0 ? tokens.inkSoft : "#AE3030"; + var s = api.coord([api.value(0), params.dataIndex]); + var e = api.coord([api.value(1), params.dataIndex]); + return { + type: "line", + shape: { x1: s[0], y1: s[1], x2: e[0], y2: e[1] }, + style: { stroke: color, lineWidth: lineWidth, opacity: opacity } + }; + }, + data: departments.map(function(_, i) { return [scoreBefore[i], scoreAfter[i]]; }), + encode: { x: [0, 1] }, + z: 1, + silent: true + }, + // "Before" endpoints — Imprint palette[0] (brand green) + // Dot size scales with |delta| to emphasize departments with larger changes + { + type: "scatter", + name: "Before", + data: departments.map(function(d, i) { + return [scoreBefore[i], d, Math.abs(deltas[i])]; + }), + encode: { x: 0, y: 1 }, + symbolSize: function(data) { return 14 + 12 * (data[2] / maxAbsDelta); }, + itemStyle: { color: tokens.palette[0] }, + z: 2 + }, + // "After" endpoints — Imprint palette[1] (lavender) + // Delta labels displayed to the right of each After dot for instant readability + { + type: "scatter", + name: "After", + data: departments.map(function(d, i) { + return [scoreAfter[i], d, Math.abs(deltas[i])]; + }), + encode: { x: 0, y: 1 }, + symbolSize: function(data) { return 14 + 12 * (data[2] / maxAbsDelta); }, + itemStyle: { color: tokens.palette[1] }, + label: { + show: true, + position: "right", + formatter: function(params) { + var delta = deltas[params.dataIndex]; + return (delta >= 0 ? "+" : "") + delta; + }, + color: tokens.inkSoft, + fontSize: 12 + }, + z: 2 + } + ] +}); diff --git a/plots/dumbbell-basic/metadata/javascript/echarts.yaml b/plots/dumbbell-basic/metadata/javascript/echarts.yaml new file mode 100644 index 0000000000..f8fc8cbddd --- /dev/null +++ b/plots/dumbbell-basic/metadata/javascript/echarts.yaml @@ -0,0 +1,281 @@ +library: echarts +language: javascript +specification_id: dumbbell-basic +created: '2026-06-30T23:10:21Z' +updated: '2026-06-30T23:32:05Z' +generated_by: claude-sonnet +workflow_run: 28481441838 +issue: 945 +language_version: 22.23.0 +library_version: 5.5.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/javascript/echarts/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/javascript/echarts/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/javascript/echarts/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/javascript/echarts/plot-dark.html +quality_score: 93 +review: + strengths: + - 'Sophisticated triple-encoding of delta magnitude: connector line width, connector + opacity, AND dot size all scale with |delta|, creating an elegant and immediately + readable visual hierarchy without annotations' + - 'Semantic color on connector lines: theme-adaptive inkSoft for gains vs matte + red (#AE3030 semantic anchor) for declines — declining departments (Legal, Finance) + immediately pop from the chart' + - Inline delta labels (+26, +24, -3) positioned right of each After dot provide + instant quantitative readability without requiring readers to estimate from axis + positions + - Sort order ascending by delta places largest-gain departments at the top — viewer + immediately reads the story from top to bottom + - 'Clean minimal chrome: no x-axis line, no tick marks, no split lines — full focus + on the dumbbell elements themselves' + - 'Correct palette usage: Before = palette[0] #009E73 (brand green, first series), + After = palette[1] #C475FD (lavender); both renders theme-correct with transparent + background inheriting page surface' + - Custom ECharts series with renderItem for connector lines is idiomatic and sophisticated + — exactly the right approach for custom geometry in ECharts + weaknesses: + - 'No x-axis split lines (grid): subtle vertical grid lines would help readers estimate + exact Efficiency Score values, especially for the middle rows where the dumbbell + endpoints don''t align to easily-read tick positions' + - Delta labels use fontSize 12 CSS px — at the lower end for a 3200px canvas; rounding + up to 13-14 CSS px would improve readability when the image is scaled to smaller + viewports + - 'Gain connector color (inkSoft = #4A4A44 light / #B8B7B0 dark) blends into the + chrome layer rather than reading as a data color — using a muted Imprint palette + tint for gains would give more visual separation between the ''positive direction'' + cue and structural elements' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white, clearly #FAF8F1 (not pure white) — confirmed correct. + Chrome: Title "Digital Transformation · dumbbell-basic · javascript · echarts · anyplot.ai" centered at top in dark ink, font scaled to ~21px CSS (appropriate for the 70-char title). Legend row beneath shows green circle "Before" and lavender circle "After" in inkSoft color. Y-axis category labels (Sales, Engineering, IT, Marketing, R&D, Logistics, HR, Operations, Finance, Legal) legible in inkSoft. X-axis "Efficiency Score" label readable. Tick values (40–100) slightly small at fontSize 13 CSS but readable. + Data: 10 horizontal dumbbells. Before dots in brand green (#009E73), After dots in lavender (#C475FD). Connector lines vary in width (1.5–5px) and opacity (0.25–0.70) proportional to |delta|. Declining connectors (Finance −3, Legal −3) render in matte red (#AE3030). Dot sizes also scale with |delta| giving prominent dots to Sales/Engineering (+26) and small ones to Finance/Legal (−3). Delta labels (+26, +24, +24, +19, +17, +17, +15, −3, −3) in inkSoft to the right of each After dot. + Legibility verdict: PASS — all text clearly readable against the light background. No light-on-light issues. + + Dark render (plot-dark.png): + Background: Warm near-black, clearly #1A1A17 (not pure black) — confirmed correct. + Chrome: Title in light ink (tokens.ink = #F0EFE8) clearly readable against dark background. Category labels, axis label, and legend text all in light inkSoft (#B8B7B0) — readable. Tick labels visible. No dark-on-dark failures observed anywhere. + Data: Data colors identical to light render — brand green Before dots, lavender After dots, matte red declining connectors. The connector size/opacity encoding carries through identically. Delta labels in #B8B7B0 (inkSoft dark) are legible though on the smaller side. + Legibility verdict: PASS — all text clearly readable against the dark background. No dark-on-dark failures. + criteria_checklist: + visual_quality: + score: 29 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All font sizes explicitly set and readable in both themes. Minor + deduction for delta labels at fontSize 12 CSS px being slightly small on + the 3200px canvas. + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping elements. Category labels well-spaced. Delta labels + clear of all other elements. + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: Dot sizes (14–26px CSS) and connector widths (1.5–5px) scale with + delta magnitude — optimal density adaptation. Declining connectors in red + enhance visibility of small-delta rows. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Green/lavender pair is CVD-safe per Imprint palette design. Matte + red for declining connectors has good contrast. No red-green-only encoding. + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas gate passed. Good margins (130 left, 90 right, 100 top, 70 + bottom CSS px). Plot fills canvas well in landscape. No content cut off. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: 'X-axis: ''Efficiency Score'' descriptive. Y-axis: category names + serve as labels. Title follows {Descriptive} · {spec-id} · {lang} · {lib} + · anyplot.ai format.' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Before series = palette[0] #009E73 (brand green, first series). + After series = palette[1] #C475FD (lavender). Connector colors are structural + (inkSoft/semantic red anchor). Background transparent → page surface. Both + renders theme-correct.' + design_excellence: + score: 15 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: 'Strong design: connector width + opacity + dot size all scale with + |delta| (triple encoding), semantic red for declines, inline delta annotations. + Clearly above defaults. Not quite publication-ready (8) but strong (6).' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: 'Good refinement: x-axis line hidden, all tick marks removed, no + split lines/grid. Left y-axis line kept for structural reference. Generous + margins. No grid limits value estimation.' + - id: DE-03 + name: Data Storytelling + score: 5 + max: 6 + passed: true + comment: 'Strong storytelling: sort by delta puts biggest gains at top, declining + departments (Legal/Finance) pop in red, delta annotations provide instant + insight. Multiple techniques working together. One step below ''excellent'' + (no callout annotations for the star performers).' + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct dumbbell/connected dot plot. Horizontal orientation with + categories on y-axis and values on x-axis as required. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Two dots per category (start/end), connecting line, distinct colors + for start/end, sorted by delta as specified. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Categories on y-axis, Efficiency Score values on x-axis (40–100 range + covers all data). Correct mapping throughout. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: 'Title: ''Digital Transformation · dumbbell-basic · javascript · + echarts · anyplot.ai'' — correct {Descriptive} · {spec-id} · {lang} · {lib} + · anyplot.ai format. Legend: Before/After with correct colors.' + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 'Shows all dumbbell aspects: both start and end values, both improvements + (8 categories) and declines (2 categories), wide range of delta magnitudes + (3 to 26). Comprehensive coverage.' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Department efficiency scores before/after digital transformation + — real business scenario, neutral, concrete department names. No controversial + content. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: 10 departments (within 5–20 spec range). Efficiency score 0–100 scale + is sensible. Values (55–91) and deltas (−3 to +26) are realistic for a digital + transformation initiative. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: No top-level functions or classes. Clean data → init → setOption + structure. Inline callbacks (renderItem, symbolSize, formatter) are required + by ECharts API, not over-engineering. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: All data hardcoded in literal arrays — fully deterministic. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: No imports — uses browser globals (window.ANYPLOT_TOKENS, echarts) + only, as required. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean, well-organized. Comments explain design intent concisely. + No fake UI elements. Appropriate complexity for a custom dumbbell in ECharts. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: 'Orientation directive present (landscape). echarts.init called correctly + — no explicit size, no devicePixelRatio. animation: false set. Harness handles + output files.' + library_mastery: + score: 9 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: Custom series with renderItem is exactly the ECharts-idiomatic approach + for custom line geometry. encode for data binding, z for layering, silent:true + for non-interactive series — all correct idiomatic patterns. + - id: LM-02 + name: Distinctive Features + score: 4 + max: 5 + passed: true + comment: renderItem in custom series is a genuinely ECharts-distinctive feature + enabling pixel-level custom rendering. encode for multi-dimensional data + binding is ECharts-specific. Strong distinctive usage, one point held for + not using tooltip formatter or other advanced ECharts-specific patterns. + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - annotations + - html-export + patterns: + - data-generation + - iteration-over-groups + dataprep: + - normalization + styling: + - alpha-blending