I followed the ChartJS documentation for creating a custom scale: https://www.chartjs.org/docs/master/samples/advanced/derived-axis-type.html
First I defined the custom scale as its own class extending the base Scale interface:
import { Scale, LinearScale, BubbleDataPoint, Chart, ChartTypeRegistry, ScatterDataPoint} from 'chart.js';
export default class SquareRootAxis extends Scale {
static defaults: {} = {};
_startValue: any;
_valueRange: number;
constructor(cfg: { id: string; type: string; ctx: CanvasRenderingContext2D; chart: Chart<keyof ChartTypeRegistry, (number | ScatterDataPoint | BubbleDataPoint)[], unknown>; }) {
super(cfg);
this._startValue = undefined;
this._valueRange = 0;
}
parse(raw: any, index: number) {
const value = LinearScale.prototype.parse.apply(this, [raw, index]);
return isFinite(value) && value > 0 ? value : null;
}
determineDataLimits() {
this.min = 0.5
this.max=31
}
buildTicks() {
const userDefinedTicks = [1, 2, 3, 5, 7, 10, 15, 20, 25, 30];
const ticks = [];
for (const tick of userDefinedTicks) {
ticks.push({
value: tick
});
}
return ticks;
}
/**
* @protected]
*/
configure() {
const start = this.min;
super.configure();
this._startValue = Math.pow(start, 1/2);
this._valueRange = Math.pow(this.max, 1/2) - Math.pow(start, 1/2);
}
getPixelForValue(value: number | undefined) {
if (value === undefined ) {
value = this.min;
}
return this.getPixelForDecimal(value === this.min ? 0 :
(Math.pow(value, 1/2) - this._startValue) / this._valueRange);
}
getValueForPixel(pixel: number) {
const decimal = this.getDecimalForPixel(pixel);
return Math.pow(this._startValue + decimal * this._valueRange, 2);
}
}
I then imported the custom scale Class and used it below:
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from 'chart.js';
import { Scatter } from 'react-chartjs-2';
import SquareRootAxis from './sqaureRootAxis';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
CubeRootAxis
);
SquareRootAxis.id = 'squareRoot';
export function Chart(props: { chartData: ChartData }) {
return <Scatter
data={props.chartData}
options={{
responsive: true,
scales: {
x: {
type: 'squareRoot',
},
},
}}
/>;
}
But when I set my chart to the custom scale name, I get the following TS error:
Type '"squareRoot"' is not assignable to type '"time" | "linear" | "logarithmic" | "category" | "timeseries"'.ts(2322) index.esm.d.ts(3618, 27): The expected type comes from property 'type' which is declared here on type '_DeepPartialObject<{ type: "time"; } & Omit<CartesianScaleOptions
It seems despite following the docs, the ChartJS scale type only recognizes the built-in scales. What am I doing wrong?
First in the sample code it looks like you have a typo in your import:
import SquareRootAxis from './sqaureRootAxis
.
Then it seems you need to register the new scale, which I cannot see in your code, as follows:
chart.register(SquareRootAxis);
For some reason this is commented at the bottom of the code in your link, and is also explained here:
https://www.chartjs.org/docs/latest/developers/axes.html
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.