diff --git a/src/components/grid.ts b/src/components/grid.ts index 45df12c..424602e 100644 --- a/src/components/grid.ts +++ b/src/components/grid.ts @@ -1,4 +1,4 @@ -import { GridOptions } from '../types'; +import { GridOptions, SvgElOptions } from '../types'; // we import only d3 types here @@ -17,12 +17,6 @@ const DEFAULT_GRID_OPTIONS = { ticksCount: DEFAULT_GRID_TICK_COUNT, }, } -export type SvgElOptions = { - height: number, - width: number, - xScale: d3.ScaleLinear, - yScale: d3.ScaleLinear, -} // Grid Class - is a core component, which can be a separate Pod in the future. (but not in current Pod terminology) @@ -31,25 +25,22 @@ export type SvgElOptions = { // svgElement should be a separate class with its own height, width, xScale, yScale params to avoid SvgElOptions as argument. // We have a general problem with passing d3 as argument everywhere. Fix it, and remove from arg in constructor here. export class Grid { - _gridOptions: GridOptions; + protected gridOptions: GridOptions; constructor( private _d3: typeof d3, private _svgEl: d3.Selection, private _svgElOptions: SvgElOptions, - gridOptions: GridOptions, + _gridOptions: GridOptions, ) { - this._gridOptions = this.setOptionDefaults(gridOptions); - - // TODO: or public method that will be called outside - this.render(); + this.gridOptions = this.setOptionDefaults(_gridOptions); } protected setOptionDefaults(gridOptions: GridOptions): GridOptions { return defaultsDeep(gridOptions, DEFAULT_GRID_OPTIONS); } - render(): void { + public render(): void { // TODO: temporary. Move out of here this._svgEl.selectAll('.grid').remove(); @@ -59,7 +50,7 @@ export class Grid { } renderGridLinesX(): void { - if(!this._gridOptions.x.isActive) { + if(!this.gridOptions.x.isActive) { return; } this._svgEl @@ -69,14 +60,14 @@ export class Grid { .style('pointer-events', 'none') .call( this._d3.axisBottom(this._svgElOptions.xScale) - .ticks(this._gridOptions.x.ticksCount) + .ticks(this.gridOptions.x.ticksCount) .tickSize(-this._svgElOptions.height) .tickFormat(() => '') ); } renderGridLinesY(): void { - if(!this._gridOptions.y.isActive) { + if(!this.gridOptions.y.isActive) { return; } this._svgEl @@ -85,7 +76,7 @@ export class Grid { .style('pointer-events', 'none') .call( this._d3.axisLeft(this._svgElOptions.yScale) - .ticks(this._gridOptions.y.ticksCount) + .ticks(this.gridOptions.y.ticksCount) .tickSize(-this._svgElOptions) .tickFormat(() => '') ); diff --git a/src/index.ts b/src/index.ts index b1f7704..e966ff3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import VueChartwerkPodMixin from './VueChartwerkPodMixin'; import { PodState } from './state'; +import { Grid } from './components/grid'; import styles from './css/style.css'; @@ -17,7 +18,8 @@ import { PanOrientation, yAxisOrientation, ScrollPanOrientation, - AxisOption + AxisOption, + SvgElOptions, } from './types'; import { uid } from './utils'; import { palette } from './colors'; @@ -101,16 +103,6 @@ const DEFAULT_OPTIONS: Options = { format: AxisFormat.NUMERIC } }, - grid: { - x: { - isActive: true, - ticksCount: 5, - }, - y: { - isActive: true, - ticksCount: 5, - }, - }, crosshair: { orientation: CrosshairOrientation.VERTICAL, color: 'red' @@ -146,6 +138,9 @@ abstract class ChartwerkPod { protected deltaYTransform = 0; protected debouncedRender = debounce(this.render.bind(this), 100); + // components + protected grid: Grid; + // TODO: test variables instead of functions with cache private _xScale: d3.ScaleLinear | null = null; private _yScale: d3.ScaleLinear | null = null; @@ -172,6 +167,9 @@ abstract class ChartwerkPod { this.d3Node = this.d3.select(this.el); this.addEventListeners(); + + this.createSvg(); + this.initComponents(); } protected addEventListeners(): void { @@ -185,7 +183,6 @@ abstract class ChartwerkPod { public render(): void { this.clearScaleCache(); - this.renderSvg(); this.renderAxes(); this.renderGrid(); @@ -237,11 +234,23 @@ abstract class ChartwerkPod { public abstract renderSharedCrosshair(values: { x?: number, y?: number }): void; public abstract hideSharedCrosshair(): void; - protected initPodState() { + protected initPodState(): void { this.state = new PodState(this.options); } - protected renderSvg(): void { + protected initComponents(): void { + // TODO: make chartContainer a separate class with SvgElOptions inside to avoid duplication + const svgElOptions = { + height: this.height, + width: this.width, + xScale: this.xScale, + yScale: this.yScale, + } + + this.grid = new Grid(this.d3, this.chartContainer, svgElOptions, this.options.grid); + } + + protected createSvg(): void { this.d3Node.select('svg').remove(); this.svg = this.d3Node .append('svg') @@ -254,40 +263,7 @@ abstract class ChartwerkPod { } protected renderGrid(): void { - this.chartContainer.selectAll('.grid').remove(); - - if(this.options.grid.x.isActive) { - this.chartContainer - .append('g') - .attr('transform', `translate(0,${this.height})`) - .attr('class', 'grid x-grid') - .style('pointer-events', 'none') - .call( - this.d3.axisBottom(this.xScale) - .ticks(this.options.grid.x.ticksCount) - .tickSize(-this.height) - .tickFormat(() => '') - ); - } - - if(this.options.grid.y.isActive) { - this.chartContainer - .append('g') - .attr('class', 'grid y-grid') - .style('pointer-events', 'none') - .call( - this.d3.axisLeft(this.yScale) - .ticks(this.options.grid.y.ticksCount) - .tickSize(-this.width) - .tickFormat(() => '') - ); - } - - this.chartContainer.selectAll('.grid').selectAll('.tick') - .attr('opacity', '0.5'); - - this.chartContainer.selectAll('.grid').select('.domain') - .style('pointer-events', 'none'); + this.grid.render(); } protected renderAxes(): void { diff --git a/src/types.ts b/src/types.ts index e2dfbcd..a082abb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -165,3 +165,9 @@ export enum yAxisOrientation { RIGHT = 'right', BOTH = 'both' } +export type SvgElOptions = { + height: number, + width: number, + xScale: d3.ScaleLinear, + yScale: d3.ScaleLinear, +}