chart

Docs › Numbers and look

Trend lines, moving averages and year-over-year comparison

series.trend adds a linear trend or moving average; compare overlays the previous period as a dashed series with change and change % in the tooltip.

A trend line shows the overall direction through values that jump around. A linear trend is the straight line closest to all values (least squares); a moving average joins the mean of the last few periods and smooths out short swings. A year-over-year comparison overlays the same months of last year so the change is visible.

In 82chart 0.5 both are one option. trend on a series draws a thin dashed line in its color; compare on the chart overlays the previous period as a muted dashed series and adds change and change % to the tooltip.

Trend lines and moving averages

Live example

Code for this example

createChart('#chart', {
  type: 'line',
  title: 'Daily visitors in September',
  data: {
    labels: Array.from({ length: 30 }, (_, i) => '2026-09-' + String(i + 1).padStart(2, '0')),
    series: [
      {
        name: 'Visitors',
        data: Array.from({ length: 30 }, (_, i) => Math.round(1200 + i * 18 + Math.sin(i * 0.9) * 160)),
        trend: 'linear',
      },
      {
        name: 'Members',
        data: Array.from({ length: 30 }, (_, i) => Math.round(520 + i * 6 + ((i + 2) % 7 < 2 ? -140 : 0) + Math.cos(i) * 40)),
        trend: { type: 'moving', period: 7 },
      },
    ],
  },
});
  • Trend lines get their own legend entries, such as "Visitors trend" and "Members 7-period moving average" (rename with trend.name), switch on and off separately and show in the tooltip.
  • Linear is a least-squares line through the points that have a value, from the first to the last of them. Moving is the trailing mean of period values (default 7); a gap (null) restarts it.
  • Line, area and bar series on a shared x. Not for scatter plots, pyramids, waterfalls or horizontal bars.
  • Trend lines are not data, so CSV, xlsx and the table leave them out.

Year over year from the data (shift)

Pass 24 months with previous: 'shift': the first 12 are the base and the latest 12 are drawn. Hover a bar for last year's value, the change and the change %. With deltaColors: 'korea' changes read ▲ red and ▼ blue.

Live example

Code for this example

createChart('#chart', {
  type: 'bar',
  title: 'Monthly sales vs the same month last year',
  prefix: '₩',
  deltaColors: 'korea',
  // 24 months in: the first 12 are the base, the latest 12 are drawn
  compare: { previous: 'shift', period: 12, label: 'Last year' },
  data: {
    labels: Array.from({ length: 24 }, (_, i) => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][i % 12] + (i < 12 ? ' 25' : ' 26')),
    series: [{
      name: 'Sales',
      data: Array.from({ length: 24 }, (_, i) => Math.round((180 + i * 4 + Math.sin(i / 1.9) * 22) * 1e6)),
    }],
  },
});
  • The spacing of 'shift' (period) comes from date x values: 12 for months, 4 quarters, 7 days (the same weekday), 24 hours, 1 otherwise. With name labels as above, set period: 12; weekly data takes period: 52.
  • The previous period is data: CSV, xlsx and the table get a column for it.

Previous period as separate data

When last year's values come from elsewhere, give previous a ChartData. Series match by order and values by position (value j of the first series is the previous value at this chart's x j).

Live example

Code for this example

createChart('#chart', {
  type: 'line',
  title: 'Sign-ups per quarter, year over year',
  compare: {
    label: 'Last year',
    previous: { series: [{ data: [4100, 4520, 4380, 5010] }] },
  },
  data: {
    labels: ['1Q', '2Q', '3Q', '4Q'].map((q) => q + ' 2026'),
    series: [{ name: 'Sign-ups', data: [4620, 4810, 5240, 5580] }],
  },
});

Options

OptionWhat it does
series[i].trend'linear', 'moving' or { type: 'linear' | 'moving', period?: 7, name? }
compare.previousA ChartData (series by order, values by position) or 'shift'
compare.labelName of the previous period (default 'Previous'), as in 'Sales (Last year)'
compare.period'shift' spacing (default: from the x spacing)
deltaColors'korea': changes as ▲ red and ▼ blue
locale.trend, movingAverage, previous, compareChange, compareRateWording

Frequently asked questions

Does year-over-year need a second axis?

No. The previous period is drawn on the same axis in the same unit, so there is no dual axis to misread; change and change % are numbers in the tooltip.

Can the legend switch a trend line off?

Yes. A trend line has its own legend entry and toggles separately; hiding the series hides its trend too.

Do trend lines and last year go into the Excel export?

The previous period is data and gets a column in CSV and xlsx; trend lines are computed guides and are left out.