|
| 1 | +// anyplot.ai |
| 2 | +// venn-labeled-items: Chartgeist-Style Venn Diagram with Labeled Items |
| 3 | +// Library: muix 7.29.1 | JavaScript 22.22.3 |
| 4 | +// Quality: 84/100 | Created: 2026-06-25 |
| 5 | +//# anyplot-orientation: landscape |
| 6 | +// anyplot.ai |
| 7 | +// venn-labeled-items: Chartgeist-Style Venn Diagram with Labeled Items |
| 8 | +// Library: MUI X Charts | React | Node 22 |
| 9 | +// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope. |
| 10 | +// Quality: pending | Created: 2026-06-25 |
| 11 | + |
| 12 | +import { ChartContainer } from "@mui/x-charts/ChartContainer"; |
| 13 | + |
| 14 | +const t = window.ANYPLOT_TOKENS; |
| 15 | + |
| 16 | +// Venn circle radius and centres — equilateral triangle, d=320, r=230 |
| 17 | +// gives clear pairwise and triple overlaps with generous whitespace |
| 18 | +const R = 230; |
| 19 | + |
| 20 | +const CIRCLES = [ |
| 21 | + { key: "A", name: "Pretentious", cx: 800, cy: 325, color: t.palette[0], lx: 800, ly: 74 }, |
| 22 | + { key: "B", name: "Delicious", cx: 640, cy: 602, color: t.palette[1], lx: 475, ly: 856 }, |
| 23 | + { key: "C", name: "Affordable", cx: 960, cy: 602, color: t.palette[2], lx: 1125, ly: 856 }, |
| 24 | +]; |
| 25 | + |
| 26 | +// Items — each placed at a coordinate that lies within its assigned zone only. |
| 27 | +// Coordinates verified analytically against all three circle boundaries. |
| 28 | +const ITEMS = [ |
| 29 | + // A only |
| 30 | + { label: "Kombucha", x: 762, y: 230 }, |
| 31 | + { label: "Matcha Latte", x: 844, y: 207 }, |
| 32 | + // AB |
| 33 | + { label: "Oat Milk Latte", x: 676, y: 413 }, |
| 34 | + { label: "Cold Brew", x: 716, y: 456 }, |
| 35 | + { label: "Flat White", x: 700, y: 499 }, |
| 36 | + // AC |
| 37 | + { label: "Sparkling Water", x: 885, y: 417 }, |
| 38 | + { label: "Energy Drink", x: 921, y: 469 }, |
| 39 | + // B only |
| 40 | + { label: "Espresso", x: 490, y: 732 }, |
| 41 | + { label: "Cappuccino", x: 528, y: 764 }, |
| 42 | + // BC — spread x-coords to reduce crowding |
| 43 | + { label: "Diner Coffee", x: 720, y: 625 }, |
| 44 | + { label: "Green Tea", x: 800, y: 665 }, |
| 45 | + { label: "Orange Juice", x: 880, y: 645 }, |
| 46 | + // C only |
| 47 | + { label: "Tap Water", x: 1074, y: 732 }, |
| 48 | + { label: "Herbal Tea", x: 1112, y: 764 }, |
| 49 | + // ABC |
| 50 | + { label: "Chai", x: 800, y: 510 }, |
| 51 | +]; |
| 52 | + |
| 53 | +export default function Chart() { |
| 54 | + const W = window.ANYPLOT_SIZE.width; |
| 55 | + const H = window.ANYPLOT_SIZE.height; |
| 56 | + |
| 57 | + return ( |
| 58 | + <ChartContainer |
| 59 | + width={W} |
| 60 | + height={H} |
| 61 | + series={[]} |
| 62 | + margin={{ top: 0, bottom: 0, left: 0, right: 0 }} |
| 63 | + sx={{ background: t.pageBg, display: "block" }} |
| 64 | + > |
| 65 | + {/* Two-line editorial title */} |
| 66 | + <text |
| 67 | + x={W / 2} |
| 68 | + y={26} |
| 69 | + textAnchor="middle" |
| 70 | + dominantBaseline="middle" |
| 71 | + fontSize={26} |
| 72 | + fontWeight="700" |
| 73 | + fill={t.ink} |
| 74 | + fontFamily="Georgia, 'Times New Roman', serif" |
| 75 | + > |
| 76 | + A Taxonomy of Beverages |
| 77 | + </text> |
| 78 | + <text |
| 79 | + x={W / 2} |
| 80 | + y={52} |
| 81 | + textAnchor="middle" |
| 82 | + dominantBaseline="middle" |
| 83 | + fontSize={13} |
| 84 | + fill={t.inkSoft} |
| 85 | + fontFamily="Arial, Helvetica, sans-serif" |
| 86 | + style={{ letterSpacing: "0.4px" }} |
| 87 | + > |
| 88 | + venn-labeled-items · javascript · muix · anyplot.ai |
| 89 | + </text> |
| 90 | + |
| 91 | + {/* Venn circles — semi-transparent fills let overlap regions show through */} |
| 92 | + {CIRCLES.map(c => ( |
| 93 | + <circle |
| 94 | + key={c.key} |
| 95 | + cx={c.cx} |
| 96 | + cy={c.cy} |
| 97 | + r={R} |
| 98 | + fill={c.color} |
| 99 | + fillOpacity={0.15} |
| 100 | + stroke={c.color} |
| 101 | + strokeOpacity={0.55} |
| 102 | + strokeWidth={2} |
| 103 | + /> |
| 104 | + ))} |
| 105 | + |
| 106 | + {/* Category labels outside each circle, uppercase serif in circle colour */} |
| 107 | + {CIRCLES.map(c => ( |
| 108 | + <text |
| 109 | + key={c.key + "-lbl"} |
| 110 | + x={c.lx} |
| 111 | + y={c.ly} |
| 112 | + textAnchor="middle" |
| 113 | + dominantBaseline="middle" |
| 114 | + fontSize={18} |
| 115 | + fontWeight="700" |
| 116 | + fill={c.color} |
| 117 | + fontFamily="Georgia, 'Times New Roman', serif" |
| 118 | + style={{ letterSpacing: "1px" }} |
| 119 | + > |
| 120 | + {c.name.toUpperCase()} |
| 121 | + </text> |
| 122 | + ))} |
| 123 | + |
| 124 | + {/* Item labels — bullet dot + text above it */} |
| 125 | + {ITEMS.map((item, i) => ( |
| 126 | + <g key={i}> |
| 127 | + <circle |
| 128 | + cx={item.x} |
| 129 | + cy={item.y} |
| 130 | + r={3.5} |
| 131 | + fill={t.inkSoft} |
| 132 | + fillOpacity={0.65} |
| 133 | + /> |
| 134 | + <text |
| 135 | + x={item.x} |
| 136 | + y={item.y - 10} |
| 137 | + textAnchor="middle" |
| 138 | + dominantBaseline="auto" |
| 139 | + fontSize={15} |
| 140 | + fill={t.ink} |
| 141 | + fontFamily="Arial, Helvetica, sans-serif" |
| 142 | + > |
| 143 | + {item.label} |
| 144 | + </text> |
| 145 | + </g> |
| 146 | + ))} |
| 147 | + </ChartContainer> |
| 148 | + ); |
| 149 | +} |
0 commit comments