{"spec_id":"polar-bar","library":"echarts","language":"javascript","code":"// anyplot.ai\n// polar-bar: Polar Bar Chart (Wind Rose)\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-09-05\n\n//# anyplot-orientation: square\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Wind-rose observations: hourly frequency counts by compass direction and\n// wind-speed bin. Prevailing westerlies with a secondary southerly lobe.\nconst directions = [\n  \"N\", \"NNE\", \"NE\", \"ENE\", \"E\", \"ESE\", \"SE\", \"SSE\",\n  \"S\", \"SSW\", \"SW\", \"WSW\", \"W\", \"WNW\", \"NW\", \"NNW\",\n];\nconst speedBins = [\"0-5 kt\", \"5-10 kt\", \"10-15 kt\", \"15-20 kt\", \"20+ kt\"];\nconst frequencies = [\n  [8, 6, 3, 1, 0], // N\n  [6, 5, 2, 1, 0], // NNE\n  [5, 4, 2, 1, 0], // NE\n  [4, 3, 2, 1, 0], // ENE\n  [4, 3, 1, 1, 0], // E\n  [3, 3, 1, 1, 0], // ESE\n  [4, 3, 2, 1, 0], // SE\n  [5, 5, 3, 1, 0], // SSE\n  [7, 8, 5, 2, 0], // S\n  [9, 11, 9, 4, 1], // SSW\n  [11, 15, 15, 8, 3], // SW\n  [10, 16, 17, 11, 4], // WSW\n  [9, 13, 13, 8, 3], // W\n  [6, 9, 8, 5, 2], // WNW\n  [5, 6, 5, 3, 1], // NW\n  [5, 5, 4, 2, 0], // NNW\n];\n\n// --- Init --------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option --------------------------------------------------------------------\n// barMinHeight reserves a visible radial band for thin stack segments so the\n// calm-direction wind-speed colors stay distinguishable near the center.\nconst series = speedBins.map((bin, binIndex) => ({\n  name: bin,\n  type: \"bar\",\n  coordinateSystem: \"polar\",\n  stack: \"wind\",\n  barMinHeight: 5,\n  data: frequencies.map((row) => row[binIndex]),\n  itemStyle: { color: t.palette[binIndex] },\n}));\n\n// Subtle amber corridor behind the prevailing SW-WSW-W wind sector — the\n// chart's natural focal point — drawn as a custom polar series so it sits\n// underneath the stacked bars (echarts' own markArea does not support the\n// polar coordinate system). Built as a sampled polygon from api.coord(),\n// which already applies the angleAxis/radiusAxis transform used by the\n// bars, so the wedge always lines up with the SW/WSW/W category bands.\nconst sectorStart = directions.indexOf(\"SW\") - 0.5;\nconst sectorEnd = directions.indexOf(\"W\") + 0.5;\nconst arcSamples = 24;\nconst highlightSector = {\n  // No `name` — keeps this annotation series out of the legend.\n  type: \"custom\",\n  coordinateSystem: \"polar\",\n  silent: true,\n  renderItem: (_params, api) => {\n    const [cx, cy] = api.coord([0, sectorStart]);\n    const points = [[cx, cy]];\n    for (let i = 0; i <= arcSamples; i += 1) {\n      const angle = sectorStart + ((sectorEnd - sectorStart) * i) / arcSamples;\n      points.push(api.coord([60, angle]));\n    }\n    return { type: \"polygon\", shape: { points }, style: { fill: t.amber, opacity: 0.12 } };\n  },\n  data: [0],\n};\n\nchart.setOption({\n  animation: false,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"polar-bar · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    top: 24,\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: 500 },\n  },\n  legend: {\n    bottom: 16,\n    left: \"center\",\n    itemWidth: 16,\n    itemHeight: 16,\n    textStyle: { color: t.ink, fontSize: 15 },\n  },\n  polar: { center: [\"50%\", \"54%\"], radius: \"62%\" },\n  angleAxis: {\n    type: \"category\",\n    data: directions,\n    startAngle: 90,\n    clockwise: true,\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  radiusAxis: {\n    type: \"value\",\n    name: \"Hours observed\",\n    min: 0,\n    max: 60,\n    nameTextStyle: { color: t.inkSoft, fontSize: 13 },\n    axisLabel: { color: t.inkSoft, fontSize: 13 },\n    axisLine: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [highlightSector, ...series],\n});\n"}