Alexander Velikiy
3 years ago
3 changed files with 134 additions and 58 deletions
@ -0,0 +1,93 @@ |
|||||||
|
import { GridOptions, SvgElParams } from '../types'; |
||||||
|
|
||||||
|
|
||||||
|
// we import only d3 types here
|
||||||
|
import * as d3 from 'd3'; |
||||||
|
|
||||||
|
import defaultsDeep from 'lodash/defaultsDeep'; |
||||||
|
|
||||||
|
const DEFAULT_GRID_TICK_COUNT = 5; |
||||||
|
const DEFAULT_GRID_OPTIONS: GridOptions = { |
||||||
|
x: { |
||||||
|
enabled: true, |
||||||
|
ticksCount: DEFAULT_GRID_TICK_COUNT, |
||||||
|
}, |
||||||
|
y: { |
||||||
|
enabled: true, |
||||||
|
ticksCount: DEFAULT_GRID_TICK_COUNT, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Grid Class - is a core component, which can be a separate Pod in the future. (but not in current Pod terminology)
|
||||||
|
// All components have construcor with required args: svg element which will be filled with this component and options for it.
|
||||||
|
// All compoтents have a reqiured method "render", which will be called in core costructor. <- this solution is temporary.
|
||||||
|
// Each component has its own default options.
|
||||||
|
// svgElement should be a separate class with its own height, width, xScale, yScale params to avoid SvgElParams 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 { |
||||||
|
protected gridOptions: GridOptions; |
||||||
|
|
||||||
|
constructor( |
||||||
|
private _d3: typeof d3, |
||||||
|
private _svgEl: d3.Selection<SVGElement, unknown, null, undefined>, |
||||||
|
private _svgElParams: SvgElParams, |
||||||
|
_gridOptions: GridOptions, |
||||||
|
) { |
||||||
|
this.gridOptions = this.setOptionDefaults(_gridOptions); |
||||||
|
} |
||||||
|
|
||||||
|
protected setOptionDefaults(gridOptions: GridOptions): GridOptions { |
||||||
|
return defaultsDeep(gridOptions, DEFAULT_GRID_OPTIONS); |
||||||
|
} |
||||||
|
|
||||||
|
public render(): void { |
||||||
|
// TODO: temporary. Move out of here
|
||||||
|
this._svgEl.selectAll('.grid').remove(); |
||||||
|
|
||||||
|
this.renderGridLinesX(); |
||||||
|
this.renderGridLinesY(); |
||||||
|
this.updateStylesOfTicks(); |
||||||
|
} |
||||||
|
|
||||||
|
renderGridLinesX(): void { |
||||||
|
if(!this.gridOptions.x.enabled) { |
||||||
|
return; |
||||||
|
} |
||||||
|
this._svgEl |
||||||
|
.append('g') |
||||||
|
.attr('transform', `translate(0,${this._svgElParams.height})`) |
||||||
|
.attr('class', 'grid x-grid') |
||||||
|
.style('pointer-events', 'none') |
||||||
|
.call( |
||||||
|
this._d3.axisBottom(this._svgElParams.xScale) |
||||||
|
.ticks(this.gridOptions.x.ticksCount) |
||||||
|
.tickSize(-this._svgElParams.height) |
||||||
|
.tickFormat(() => '') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
renderGridLinesY(): void { |
||||||
|
if(!this.gridOptions.y.enabled) { |
||||||
|
return; |
||||||
|
} |
||||||
|
this._svgEl |
||||||
|
.append('g') |
||||||
|
.attr('class', 'grid y-grid') |
||||||
|
.style('pointer-events', 'none') |
||||||
|
.call( |
||||||
|
this._d3.axisLeft(this._svgElParams.yScale) |
||||||
|
.ticks(this.gridOptions.y.ticksCount) |
||||||
|
.tickSize(-this._svgElParams) |
||||||
|
.tickFormat(() => '') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
updateStylesOfTicks(): void { |
||||||
|
// TODO: add options for these actions
|
||||||
|
this._svgEl.selectAll('.grid').selectAll('.tick') |
||||||
|
.attr('opacity', '0.5'); |
||||||
|
this._svgEl.selectAll('.grid').select('.domain') |
||||||
|
.style('pointer-events', 'none'); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue