Chart.js icon indicating copy to clipboard operation
Chart.js copied to clipboard

Can't register a custom scale on chartjs

Open visantiago99 opened this issue 3 years ago • 2 comments

Expected behavior

I'm trying to create a custom scale using ChartJs version 3.9.1, where it says to create a custom scale you just need to create a class that extends Chart.Scale from 'chartjs'.

After creating this class they tell you need to set the id property in order to access this id in chart options as

scales:{y: {type: 'MyScale'}}

image

Current behavior

The problem is that the interface of Chart.Scale says that its Id is readonly, so I cant se't it.

That's my code so far:

import {
  ChartComponentLike, Tick, Scale, Chart,
} from 'chart.js';
import StringUtils from '../../../lib/string';

class PowerFactorScale extends Scale {
  public determineDataLimits() {
    const withWorstIndValue = (previousValue: number, nextValue: number) => (nextValue > 0
            && nextValue < previousValue
      ? nextValue - 0.01
      : previousValue);
    const toWorstIndValue = (dataset: any) => dataset.data.reduce(withWorstIndValue, 1);

    const withWorstCapValue = (previousValue: number, nextValue: number) => (nextValue < 0
            && nextValue > previousValue
      ? nextValue - 0.01
      : previousValue);
    const toWorstCapValue = (dataset: any) => dataset.data.reduce(withWorstCapValue, -1);

    const worstIndValues: number[] = this.chart.data.datasets.map(toWorstIndValue);
    const worstCapValues: number[] = this.chart.data.datasets.map(toWorstCapValue);

    worstIndValues.push(0.88);
    worstCapValues.push(-0.88);
    this.max = Math.min(...worstIndValues);
    this.min = Math.max(...worstCapValues);
  }

  public buildTicks(): Tick[] {
    const worstPossibleValue = Math.min(
      Math.abs(this.max),
      Math.abs(this.min),
    );

    const interval = (1 - worstPossibleValue) / 3;
    const firstInterval = 1 - interval;
    const middleInterval = 1 - interval * 2;
    const lastInterval = 1 - interval * 3;

    // eslint-disable-next-line no-return-assign
    return this.ticks = [
      lastInterval,
      middleInterval,
      firstInterval,
      1,
      -firstInterval,
      -middleInterval,
      -lastInterval,
    ].map(StringUtils.toPowerFactorScale) as unknown as Tick[];
  }

  public getLabelForIndex(index: number, datasetIndex: number) {
    return this.chart.data.datasets[datasetIndex].data[index];
  }

  public getPixelForTick(index: number) {
    const { chartArea } = this.chart;
    const chartHeight = chartArea.bottom - chartArea.top;
    const tickHeight = chartHeight / (this.ticks.length - 1);

    return index * tickHeight + chartArea.top;
  }

  public getPixelForValue(value: number) {
    const { chartArea } = this.chart;
    const chartHeight = chartArea.bottom - chartArea.top;
    const tickHeight = chartHeight / (this.ticks.length - 1);
    // eslint-disable-next-line no-mixed-operators
    const chartCenter = tickHeight * (this.ticks.length - 1) / 2 + chartArea.top;

    const worstPossibleValue = Math.min(
      Math.abs(this.max),
      Math.abs(this.min),
    );

    const interval = (1 - worstPossibleValue) / 3;
    const heightPerValue = tickHeight / interval;

    if (value === 0) {
      return chartCenter;
    }

    if (value === 1) {
      return chartCenter - 0.003 * heightPerValue;
    }

    if (value > 0) {
      return Math.min(chartHeight, chartCenter - (1 - value) * heightPerValue);
    }

    return Math.min(chartHeight, chartCenter - (-1 - value) * heightPerValue);
  }
}

PowerFactorScale.prototype.id = 'teste';

Chart.register(PowerFactorScale as unknown as ChartComponentLike);

// Chart.registry.addScales(PowerFactorScale as unknown as ChartComponentLike);

I've tried to set the id doing this.id = 'test' but it keeps saying I can't set it because its readonly.

image

Reproducible sample

https://www.typescriptlang.org/play?#

Optional extra steps/info to reproduce

No response

Possible solution

No response

Context

No response

chart.js version

3.9.1

Browser name and version

No response

Link to your project

No response

visantiago99 avatar Dec 14 '22 11:12 visantiago99

Can you try to set the id in the class constructor?

gbaron avatar Dec 17 '22 20:12 gbaron

This works for me.

export class MyScale extends Scale {
  static id: string = 'myScale';
}

wokis avatar Apr 11 '24 09:04 wokis