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 debouncedRender = debounce(this.render.bind(this), 100);
protected svgElParams: SvgElParams;
// components
protected grid: Grid;
@ -162,12 +163,11 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
this.series = cloneDeep(_series);
this.d3 = _d3;
this.initPodState();
this.d3Node = this.d3.select(this.el);
this.addEventListeners();
this.createSvg();
this.initPodState();
this.initComponents();
}
@ -233,16 +233,21 @@ abstract class ChartwerkPod<T extends TimeSerie, O extends Options> {
public abstract hideSharedCrosshair(): 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 {
// TODO: make chartContainer a separate class with SvgElParams inside to avoid duplication
// TODO: bad connection between State and Grid
const svgElParams = {
height: this.height,
width: this.width,
xScale: this.xScale,
yScale: this.yScale,
xScale: this.state.xScale,
yScale: this.state.yScale,
}
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]);
}
// TODO: scales should be moved to State. Because it dependes on changeable ranges
get xScale(): d3.ScaleLinear<number, number> {
if(this._xScale === null) {
const domain = this.state.xValueRange;
this._xScale = this.d3.scaleLinear()
.domain(domain)
.range([0, this.width]);
}
return this._xScale;
return this.state.xScale;
}
get yScale(): d3.ScaleLinear<number, number> {
if(this._yScale === null) {
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;
return this.state.yScale;
}
protected get y1Scale(): d3.ScaleLinear<number, number> {
if(this.state.isSeriesUnavailable || this.options.axis.y1 === undefined || this.options.axis.y1.isActive === false) {
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;
return this.state.y1Scale;
}
getd3TimeRangeEvery(count: number): d3.TimeInterval {

67
src/state.ts

@ -1,10 +1,15 @@
import { TimeSerie, Options, yAxisOrientation } from './types';
// we import only d3 types here
import * as d3 from 'd3';
import cloneDeep from 'lodash/cloneDeep';
import min from 'lodash/min';
import minBy from 'lodash/minBy';
import max from 'lodash/max';
import maxBy from 'lodash/maxBy';
import sortBy from 'lodash/sortBy';
import reverse from 'lodash/reverse';
const DEFAULT_AXIS_RANGE = [0, 1];
@ -14,29 +19,80 @@ const DEFAULT_TRANSFORM = {
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: add scales
// TODO: PodState can be divided in two classes, but it is hard now.
export class PodState<T extends TimeSerie, O extends Options> {
private _xValueRange: [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 _xScale: d3.ScaleLinear<number, number>;
private _yScale: d3.ScaleLinear<number, number>;
private _y1Scale: d3.ScaleLinear<number, number>;
constructor(
protected _d3: typeof d3,
protected boxParams: { height: number, width: number },
protected series: T[],
protected options: O,
) {
this.initRanges();
this.initScales();
}
protected initRanges(): void {
this._xValueRange = [this.minValueX, this.maxValueX];
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 {
@ -57,14 +113,17 @@ export class PodState<T extends TimeSerie, O extends Options> {
set xValueRange(range: [number, number]) {
this._xValueRange = range;
this.setXScale();
}
set yValueRange(range: [number, number]) {
this._yValueRange = range;
this.setYScale();
}
set y1ValueRange(range: [number, number]) {
this._y1ValueRange = range;
this.setY1Scale();
}
set transform(transform: { x?: number, y?: number, k?: number }) {

Loading…
Cancel
Save