{"spec_id":"bar-grouped","library":"echarts","language":"javascript","code":"// anyplot.ai\n// bar-grouped: Grouped Bar Chart\n// Library: echarts 6.1.0 | JavaScript 22.23.1\n// Quality: 91/100 | Created: 2026-08-05\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Quarterly revenue ($K) by product line across regions\n// West flips the usual Electronics-leads rank order: an in-store apparel\n// campaign put Apparel ahead of Electronics that quarter.\nconst regions = [\"North\", \"South\", \"East\", \"West\", \"Central\"];\nconst productLines = [\"Electronics\", \"Apparel\", \"Home Goods\"];\nconst revenue = {\n  Electronics: [420, 380, 510, 340, 390],\n  Apparel: [310, 340, 280, 460, 260],\n  \"Home Goods\": [180, 210, 195, 220, 175],\n};\nconst overallAverage =\n  Object.values(revenue)\n    .flat()\n    .reduce((sum, v) => sum + v, 0) / (regions.length * productLines.length);\n\n// --- Init ---------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option ---------------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"bar-grouped · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    top: 30,\n    textStyle: { color: t.ink, fontSize: 22 },\n  },\n  legend: {\n    data: productLines,\n    top: 90,\n    textStyle: { color: t.ink, fontSize: 16 },\n    itemWidth: 18,\n    itemHeight: 12,\n  },\n  tooltip: {\n    trigger: \"axis\",\n    axisPointer: { type: \"shadow\" },\n    valueFormatter: (v) => `$${v}K`,\n  },\n  grid: { left: 110, right: 60, top: 160, bottom: 80 },\n  xAxis: {\n    type: \"category\",\n    data: regions,\n    name: \"Region\",\n    nameLocation: \"middle\",\n    nameGap: 45,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"value\",\n    name: \"Revenue ($K)\",\n    nameLocation: \"middle\",\n    nameGap: 70,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: productLines.map((name, i) => ({\n    name,\n    type: \"bar\",\n    data: revenue[name],\n    itemStyle: {\n      color: t.palette[i],\n      borderRadius: [4, 4, 0, 0],\n      shadowBlur: 6,\n      shadowColor: \"rgba(0, 0, 0, 0.12)\",\n    },\n    emphasis: { focus: \"series\" },\n    barGap: \"12%\",\n    barCategoryGap: \"32%\",\n    ...(i === 0\n      ? {\n          markPoint: {\n            symbol: \"pin\",\n            symbolSize: 46,\n            itemStyle: { color: t.palette[0] },\n            label: { color: \"#fff\", fontSize: 12, fontWeight: 600, formatter: \"${c}K\" },\n            data: [{ type: \"max\", name: \"Peak\" }],\n          },\n          markLine: {\n            symbol: \"none\",\n            lineStyle: { color: t.inkSoft, type: \"dashed\", width: 1.5 },\n            label: {\n              color: t.inkSoft,\n              fontSize: 12,\n              formatter: `Avg ${overallAverage.toFixed(0)}K`,\n              position: \"insideEndTop\",\n            },\n            data: [{ yAxis: overallAverage, name: \"Overall average\" }],\n          },\n        }\n      : {}),\n  })),\n});\n"}