Browse Source

move scales to state

merge-requests/6/head
vargburz 3 years ago
parent
commit
5119f72c32
  1. 52
      src/index.ts
  2. 67
      src/state.ts

52
src/index.ts

@ -138,6 +138,7 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
protected deltaYTransform = 0; protected deltaYTransform = 0;
protected debouncedRender = debounce(this.render.bind(this), 100); protected debouncedRender = debounce(this.render.bind(this), 100);
protected svgElParams: SvgElParams;
// components // components
protected grid: Grid; protected grid: Grid;
@ -162,12 +163,11 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
this.series = cloneDeep(_series); this.series = cloneDeep(_series);
this.d3 = _d3; this.d3 = _d3;
this.initPodState();
this.d3Node = this.d3.select(this.el); this.d3Node = this.d3.select(this.el);
this.addEventListeners(); this.addEventListeners();
this.createSvg(); this.createSvg();
this.initPodState();
this.initComponents(); this.initComponents();
} }
@ -233,16 +233,21 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
public abstract hideSharedCrosshair(): void; public abstract hideSharedCrosshair(): void;
protected initPodState(): void { protected initPodState(): void {
this.state = new PodState(this.series, this.options); const boxPararms = {
height: this.height,
width: this.width,
}
this.state = new PodState(this.d3, boxPararms, this.series, this.options);
} }
protected initComponents(): void { protected initComponents(): void {
// TODO: make chartContainer a separate class with SvgElParams inside to avoid duplication // TODO: make chartContainer a separate class with SvgElParams inside to avoid duplication
// TODO: bad connection between State and Grid
const svgElParams = { const svgElParams = {
height: this.height, height: this.height,
width: this.width, width: this.width,
xScale: this.xScale, xScale: this.state.xScale,
yScale: this.yScale, yScale: this.state.yScale,
} }
this.grid = new Grid(this.d3, this.chartContainer, svgElParams, this.options.grid); this.grid = new Grid(this.d3, this.chartContainer, svgElParams, this.options.grid);
@ -848,47 +853,16 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
.range([0, this.height]); .range([0, this.height]);
} }
// TODO: scales should be moved to State. Because it dependes on changeable ranges
get xScale(): d3.ScaleLinear<number, number> { get xScale(): d3.ScaleLinear<number, number> {
if(this._xScale === null) { return this.state.xScale;
const domain = this.state.xValueRange;
this._xScale = this.d3.scaleLinear()
.domain(domain)
.range([0, this.width]);
}
return this._xScale;
} }
get yScale(): d3.ScaleLinear<number, number> { get yScale(): d3.ScaleLinear<number, number> {
if(this._yScale === null) { return this.state.yScale;
let domain = this.state.yValueRange;
domain = sortBy(domain) as [number, number];
if(this.options.axis.y.invert === true) {
domain = reverse(domain);
}
this._yScale = this.d3.scaleLinear()
.domain(domain)
.range([this.height, 0]); // inversed, because d3 y-axis goes from top to bottom
}
return this._yScale;
} }
protected get y1Scale(): d3.ScaleLinear<number, number> { protected get y1Scale(): d3.ScaleLinear<number, number> {
if(this.state.isSeriesUnavailable || this.options.axis.y1 === undefined || this.options.axis.y1.isActive === false) { return this.state.y1Scale;
return null;
}
// scale for y1 axis(right y axis)
if(this._y1Scale === null) {
let domain = this.state.y1ValueRange;
domain = sortBy(domain) as [number, number];
if(this.options.axis.y1.invert === true) {
domain = reverse(domain);
}
this._y1Scale = this.d3.scaleLinear()
.domain(domain)
.range([this.height, 0]); // inversed, because d3 y-axis goes from top to bottom
}
return this._y1Scale;
} }
getd3TimeRangeEvery(count: number): d3.TimeInterval { getd3TimeRangeEvery(count: number): d3.TimeInterval {

67
src/state.ts

@ -1,10 +1,15 @@
import { TimeSerie, Options, yAxisOrientation } from './types'; import { TimeSerie, Options, yAxisOrientation } from './types';
// we import only d3 types here
import * as d3 from 'd3';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import min from 'lodash/min'; import min from 'lodash/min';
import minBy from 'lodash/minBy'; import minBy from 'lodash/minBy';
import max from 'lodash/max'; import max from 'lodash/max';
import maxBy from 'lodash/maxBy'; import maxBy from 'lodash/maxBy';
import sortBy from 'lodash/sortBy';
import reverse from 'lodash/reverse';
const DEFAULT_AXIS_RANGE = [0, 1]; const DEFAULT_AXIS_RANGE = [0, 1];
@ -14,29 +19,80 @@ const DEFAULT_TRANSFORM = {
k: 1 k: 1
} }
// TODO: replace all getters with fields. Because getters will be recalculated on each call // TODO: replace all getters with fields. Because getters will be recalculated on each call. Use scales as example.
// TODO: remove duplicates in max/min values. // TODO: remove duplicates in max/min values.
// TODO: add scales // TODO: add scales
// TODO: PodState can be divided in two classes, but it is hard now. // TODO: PodState can be divided in two classes, but it is hard now.
export class PodState<T extends TimeSerie, O extends Options> { export class PodState<T extends TimeSerie, O extends Options> {
private _xValueRange: [number, number]; private _xValueRange: [number, number];
private _yValueRange: [number, number]; private _yValueRange: [number, number];
private _y1ValueRange: [number, number] | undefined = undefined; // can be undefined, because y1 - is an optional param private _y1ValueRange: [number, number];
private _transform: { x: number, y: number, k: number } = cloneDeep(DEFAULT_TRANSFORM); private _transform: { x: number, y: number, k: number } = cloneDeep(DEFAULT_TRANSFORM);
private _xScale: d3.ScaleLinear<number, number>;
private _yScale: d3.ScaleLinear<number, number>;
private _y1Scale: d3.ScaleLinear<number, number>;
constructor( constructor(
protected _d3: typeof d3,
protected boxParams: { height: number, width: number },
protected series: T[], protected series: T[],
protected options: O, protected options: O,
) { ) {
this.initRanges(); this.initRanges();
this.initScales();
} }
protected initRanges(): void { protected initRanges(): void {
this._xValueRange = [this.minValueX, this.maxValueX]; this._xValueRange = [this.minValueX, this.maxValueX];
this._yValueRange = [this.minValueY, this.maxValueY]; this._yValueRange = [this.minValueY, this.maxValueY];
if(this.options.axis.y1.isActive) { this._y1ValueRange = [this.minValueY1, this.maxValueY1];
this._y1ValueRange = [this.minValueY1, this.maxValueY1]; }
protected initScales(): void {
this.setXScale();
this.setYScale();
this.setY1Scale();
}
protected setYScale(): void {
let domain = this._yValueRange;
domain = sortBy(domain) as [number, number];
if(this.options.axis.y.invert === true) {
domain = reverse(domain);
}
this._yScale = this._d3.scaleLinear()
.domain(domain)
.range([this.boxParams.height, 0]); // inversed, because d3 y-axis goes from top to bottom;
}
protected setXScale(): void {
const domain = this._xValueRange;
this._xScale = this._d3.scaleLinear()
.domain(domain)
.range([0, this.boxParams.width]);
}
protected setY1Scale(): void {
let domain = this._y1ValueRange;
domain = sortBy(domain) as [number, number];
if(this.options.axis.y1.invert === true) {
domain = reverse(domain);
} }
this._y1Scale = this._d3.scaleLinear()
.domain(domain)
.range([this.boxParams.height, 0]); // inversed, because d3 y-axis goes from top to bottom
}
get yScale(): d3.ScaleLinear<number, number> {
return this._yScale;
}
get xScale(): d3.ScaleLinear<number, number> {
return this._xScale;
}
get y1Scale(): d3.ScaleLinear<number, number> {
return this._y1Scale;
} }
get xValueRange(): [number, number] | undefined { get xValueRange(): [number, number] | undefined {
@ -57,14 +113,17 @@ export class PodState<T extends TimeSerie, O extends Options> {
set xValueRange(range: [number, number]) { set xValueRange(range: [number, number]) {
this._xValueRange = range; this._xValueRange = range;
this.setXScale();
} }
set yValueRange(range: [number, number]) { set yValueRange(range: [number, number]) {
this._yValueRange = range; this._yValueRange = range;
this.setYScale();
} }
set y1ValueRange(range: [number, number]) { set y1ValueRange(range: [number, number]) {
this._y1ValueRange = range; this._y1ValueRange = range;
this.setY1Scale();
} }
set transform(transform: { x?: number, y?: number, k?: number }) { set transform(transform: { x?: number, y?: number, k?: number }) {

Loading…
Cancel
Save