Polar Line Plot — Highcharts

A line plot rendered in polar coordinates, where data points are connected with lines around a circular axis. The angle (theta) typically represents a cyclical variable while the radius shows magnitude.

Polar Line Plot rendered with Highcharts

Renders

JavaScript source (Highcharts)

// anyplot.ai
// polar-line: Polar Line Plot
// Library: highcharts 12.6.0 | JavaScript 22.23.2
// Quality: 90/100 | Created: 2026-09-05
//# anyplot-orientation: square

const t = window.ANYPLOT_TOKENS;

// --- Data (in-memory, deterministic) ----------------------------------------
// Average household electricity demand (kWh) by hour of day. Weekday shows the
// classic double peak (commute-driven morning ramp, evening cooking/lighting);
// weekend is flatter with one broad midday-into-evening bump instead of a sharp
// morning spike.
const weekdayKwh = [
  0.32, 0.28, 0.26, 0.25, 0.27, 0.34, 0.52, 0.88, 0.95, 0.62, 0.48, 0.44, 0.42,
  0.4, 0.38, 0.41, 0.5, 0.68, 1.05, 1.22, 1.1, 0.82, 0.58, 0.42,
];
const weekendKwh = [
  0.4, 0.36, 0.33, 0.31, 0.3, 0.32, 0.38, 0.48, 0.58, 0.66, 0.72, 0.78, 0.82,
  0.8, 0.76, 0.74, 0.78, 0.88, 0.98, 1.02, 0.94, 0.8, 0.62, 0.48,
];

// --- Polar -> Cartesian ------------------------------------------------------
// Core Highcharts has no `chart.polar` (that lives in the unloaded highcharts-more
// module — see prompts/library/highcharts.md "No add-on modules"). Instead of
// returning NOT_FEASIBLE, the polar geometry is built by hand: each (hour, kWh)
// reading is converted to an (x, y) pair and drawn as a genuine line series on a
// hidden, equal-range Cartesian grid, with the angular/radial gridlines drawn to
// the same scale via the renderer — real coordinates, not a picture of a polar
// chart.
const HOURS = 24;
const AXIS_MAX = 1.3; // kWh — outer ring radius, headroom over the 1.22 peak
const RADIUS_TICKS = [0.3, 0.6, 0.9, 1.2];

function polarPoint(radius, hour) {
  const theta = (hour / HOURS) * 2 * Math.PI; // 0 = top (midnight), clockwise
  return { x: radius * Math.sin(theta), y: radius * Math.cos(theta) };
}

function seriesData(values, name) {
  const points = values.map((kwh, hour) => ({
    ...polarPoint(kwh, hour),
    custom: { hour, kwh },
  }));
  points.push({ ...points[0] }); // close the loop: repeat hour 0 at the end
  return { name, data: points };
}

const weekday = seriesData(weekdayKwh, "Weekday");
const weekend = seriesData(weekendKwh, "Weekend");

// --- Chart -------------------------------------------------------------------
Highcharts.chart("container", {
  chart: {
    type: "line",
    backgroundColor: "transparent",
    animation: false,
    margin: [160, 140, 120, 140],
    style: { fontFamily: "inherit" },
    events: {
      render() {
        const chart = this;
        if (chart.polarGrid) chart.polarGrid.destroy();
        const group = chart.renderer.g("polar-grid").add();
        group.attr({ zIndex: 1 });
        const xAxis = chart.xAxis[0];
        const yAxis = chart.yAxis[0];
        const cx = xAxis.toPixels(0);
        const cy = yAxis.toPixels(0);

        // Concentric radius rings, labeled along the 15:00 spoke — at that hour
        // both series sit comfortably clear of every ring, unlike the 01:00
        // spoke where the 0.3 ring used to crowd the lines (values ~0.28-0.36
        // kWh at hour 1, right on top of the ring).
        RADIUS_TICKS.forEach((r) => {
          const rPix = Math.abs(xAxis.toPixels(r) - cx);
          chart.renderer
            .circle(cx, cy, rPix)
            .attr({ fill: "none", stroke: t.grid, "stroke-width": 1 })
            .add(group);
          const labelAt = polarPoint(r, 15);
          chart.renderer
            .text(`${r.toFixed(1)} kWh`, xAxis.toPixels(labelAt.x) + 4, yAxis.toPixels(labelAt.y) - 4)
            .css({ color: t.inkSoft, fontSize: "12px" })
            .add(group);
        });

        // Radial spokes + hour labels every 3 hours.
        for (let hour = 0; hour < HOURS; hour += 3) {
          const edge = polarPoint(AXIS_MAX, hour);
          chart.renderer
            .path(["M", cx, cy, "L", xAxis.toPixels(edge.x), yAxis.toPixels(edge.y)])
            .attr({ stroke: t.grid, "stroke-width": 1 })
            .add(group);

          const labelAt = polarPoint(AXIS_MAX * 1.1, hour);
          chart.renderer
            .text(`${String(hour).padStart(2, "0")}:00`, xAxis.toPixels(labelAt.x), yAxis.toPixels(labelAt.y))
            .attr({ align: "center" })
            .css({ color: t.inkSoft, fontSize: "14px" })
            .add(group);
        }

        chart.polarGrid = group;
      },
    },
  },
  credits: { enabled: false },
  colors: t.palette,
  title: {
    text: "Hourly Energy Demand · polar-line · javascript · highcharts · anyplot.ai",
    style: { color: t.ink, fontSize: "20px", fontWeight: "600" },
  },
  subtitle: {
    text: "Average U.S. household electricity use by hour, weekday vs. weekend",
    style: { color: t.inkSoft, fontSize: "14px" },
  },
  xAxis: { min: -AXIS_MAX, max: AXIS_MAX, visible: false },
  yAxis: { min: -AXIS_MAX, max: AXIS_MAX, visible: false, title: { text: null } },
  legend: {
    itemStyle: { color: t.inkSoft, fontSize: "14px" },
    itemHoverStyle: { color: t.ink },
  },
  tooltip: {
    backgroundColor: t.elevatedBg,
    style: { color: t.ink },
    formatter() {
      const { hour, kwh } = this.point.custom;
      return `<b>${this.series.name}</b><br>${String(hour).padStart(2, "0")}:00 — ${kwh.toFixed(2)} kWh`;
    },
  },
  plotOptions: {
    series: {
      animation: false,
      lineWidth: 2.5,
      marker: { radius: 6, lineWidth: 0 },
    },
  },
  series: [weekday, weekend],
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/polar-line/highcharts/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "polar-line",
  "language": "javascript",
  "library": "highcharts",
  "page": "https://anyplot.ai/polar-line/javascript/highcharts",
  "hub": "https://anyplot.ai/polar-line",
  "code_json": "https://api.anyplot.ai/specs/polar-line/highcharts/code",
  "spec_json": "https://api.anyplot.ai/specs/polar-line",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/polar-line/javascript/highcharts/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/polar-line/javascript/highcharts/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/polar-line/javascript/highcharts/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/polar-line/javascript/highcharts/plot-dark.html",
  "quality_score": 90.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Polar Line Plot on anyplot.ai.

Other implementations