update area render type #69

Merged
vargburz merged 2 commits from update-area-type-render into main 3 months ago
  1. 39
      examples/area.html
  2. 67
      src/index.ts
  3. 4
      src/models/line_series.ts
  4. 14
      src/types.ts

39
examples/area.html

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
let options = {
renderLegend: false, usePanning: false,
axis: {
y: { invert: false, range: [0, 100] },
x: { format: 'numeric', range: [0, 100] },
},
zoomEvents: {
mouse: { zoom: { isActive: false, orientation: 'horizontal' } },
scroll: { zoom: { isActive: false, orientation: 'horizontal' } }
},
}
const data1 = [[0,0], [35, 40], [65, 60], [100, 100]];
const data2 = [[0,0], [35, 50], [65, 65], [80, 100]];
const data3 = [[0,0], [35, 20], [65, 50], [100, 80]];
var pod = new LinePod(
document.getElementById('chart'),
[
{ target: 'test1', datapoints: data1, color: 'green' },
{ target: 'test2', datapoints: data2, color: 'blue', renderArea: 'Below' },
{ target: 'test3', datapoints: data3, color: 'orange', renderArea: 'Above' },
],
options
);
pod.render();
</script>
</body>
</html>

67
src/index.ts

@ -1,5 +1,5 @@
import { ChartwerkPod, VueChartwerkPodMixin, TimeFormat, CrosshairOrientation, BrushOrientation, yAxisOrientation } from '@chartwerk/core'; import { ChartwerkPod, VueChartwerkPodMixin, TimeFormat, CrosshairOrientation, BrushOrientation, yAxisOrientation } from '@chartwerk/core';
import { LineTimeSerie, LineOptions, MouseObj } from './types'; import { LineTimeSerie, LineOptions, MouseObj, AreaType } from './types';
import { Markers } from './components/markers'; import { Markers } from './components/markers';
import { Segments } from './components/segments'; import { Segments } from './components/segments';
@ -14,14 +14,9 @@ const METRIC_CIRCLE_RADIUS = 1.5;
const CROSSHAIR_CIRCLE_RADIUS = 3; const CROSSHAIR_CIRCLE_RADIUS = 3;
const CROSSHAIR_BACKGROUND_RAIDUS = 9; const CROSSHAIR_BACKGROUND_RAIDUS = 9;
const CROSSHAIR_BACKGROUND_OPACITY = 0.3; const CROSSHAIR_BACKGROUND_OPACITY = 0.3;
type Generator = d3.Line<[number, number]> | d3.Area<[number, number]>;
class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> { class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
lineGenerator = null;
areaGenerator = null;
lineGeneratorY1 = null;
areaGeneratorY1 = null;
private _markersLayer: Markers = null; private _markersLayer: Markers = null;
private _segmentsLayer: Segments = null; private _segmentsLayer: Segments = null;
@ -40,15 +35,14 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
this.clearAllMetrics(); this.clearAllMetrics();
this.updateCrosshair(); this.updateCrosshair();
this.initLineGenerator();
this.initAreaGenerator();
if(!this.series.isSeriesAvailable) { if(!this.series.isSeriesAvailable) {
this.renderNoDataPointsMessage(); this.renderNoDataPointsMessage();
return; return;
} }
for(const serie of this.series.visibleSeries) { for(const serie of this.series.visibleSeries) {
this._renderMetric(serie); const generator = this.getRenderGenerator(serie.renderArea, serie.yOrientation);
this._renderMetric(serie, generator);
} }
if(this._markersConf !== undefined) { if(this._markersConf !== undefined) {
this._markersLayer = new Markers(this.d3Node, this._markersConf, this.state, this.margin); this._markersLayer = new Markers(this.d3Node, this._markersConf, this.state, this.margin);
@ -65,31 +59,28 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
this._markersLayer?.clear(); this._markersLayer?.clear();
} }
initLineGenerator(): void {
this.lineGenerator = d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => this.state.yScale(d[1]));
this.lineGeneratorY1 = d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => this.state.y1Scale(d[1]));
}
initAreaGenerator(): void { getRenderGenerator(renderArea: AreaType, yOrientation: yAxisOrientation): Generator {
this.areaGenerator = d3.area() const yScale = yOrientation === yAxisOrientation.LEFT ? this.state.yScale : this.state.y1Scale;
switch(renderArea) {
case AreaType.NONE:
// return line generator
return d3.line()
.x(d => this.state.xScale(d[0])) .x(d => this.state.xScale(d[0]))
.y1(d => this.state.yScale(d[1])) .y(d => yScale(d[1]));
.y0(d => this.height); case AreaType.ABOVE:
this.areaGeneratorY1 = d3.area() return d3.area()
.x(d => this.state.xScale(d[0])) .x(d => this.state.xScale(d[0]))
.y1(d => this.state.y1Scale(d[1])) .y0(this.height)
.y0(d => this.height); .y1(d => yScale(d[1]));
} case AreaType.BELOW:
return d3.area()
getRenderGenerator(renderArea: boolean, yOrientation: yAxisOrientation): any { .x(d => this.state.xScale(d[0]))
if(renderArea) { .y0(d => yScale(d[1]))
return yOrientation === yAxisOrientation.LEFT ? this.areaGenerator : this.areaGeneratorY1; .y1(0);
default:
throw new Error(`Unknown type of renderArea: ${renderArea}`);
} }
return yOrientation === yAxisOrientation.LEFT ? this.lineGenerator : this.lineGeneratorY1;
} }
_renderDots(serie: LineTimeSerie): void { _renderDots(serie: LineTimeSerie): void {
@ -105,9 +96,9 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('cy', d => this.state.getYScaleByOrientation(serie.yOrientation)(d[1])); .attr('cy', d => this.state.getYScaleByOrientation(serie.yOrientation)(d[1]));
} }
_renderLines(serie: LineTimeSerie): void { _renderLines(serie: LineTimeSerie, generator: Generator): void {
const fillColor = serie.renderArea ? serie.color : 'none'; const fillColor = serie.renderArea !== AreaType.NONE ? serie.color : 'none';
const fillOpacity = serie.renderArea ? 0.5 : 'none'; const fillOpacity = serie.renderArea !== AreaType.NONE ? 0.5 : 'none';
this.metricContainer this.metricContainer
.append('path') .append('path')
@ -120,12 +111,12 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('stroke-opacity', 0.7) .attr('stroke-opacity', 0.7)
.attr('pointer-events', 'none') .attr('pointer-events', 'none')
.style('stroke-dasharray', serie.dashArray) .style('stroke-dasharray', serie.dashArray)
.attr('d', this.getRenderGenerator(serie.renderArea, serie.yOrientation)); .attr('d', generator);
} }
_renderMetric(serie: LineTimeSerie): void { _renderMetric(serie: LineTimeSerie, generator: Generator): void {
if(serie.renderLines === true) { if(serie.renderLines === true) {
this._renderLines(serie); this._renderLines(serie, generator);
} }
if(serie.renderDots === true) { if(serie.renderDots === true) {
@ -490,4 +481,4 @@ export const VueChartwerkLinePod = {
} }
}; };
export { LineTimeSerie, LineOptions, TimeFormat, LinePod }; export { LineTimeSerie, LineOptions, TimeFormat, LinePod, AreaType };

4
src/models/line_series.ts

@ -1,5 +1,5 @@
import { CoreSeries, yAxisOrientation } from '@chartwerk/core'; import { CoreSeries, yAxisOrientation } from '@chartwerk/core';
import { LineTimeSerie } from '../types'; import { LineTimeSerie, AreaType } from '../types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -10,7 +10,7 @@ const LINE_SERIE_DEFAULTS = {
renderLines: true, renderLines: true,
dashArray: '0', dashArray: '0',
class: '', class: '',
renderArea: false, renderArea: AreaType.NONE,
yOrientation: yAxisOrientation.LEFT, yOrientation: yAxisOrientation.LEFT,
}; };

14
src/types.ts

@ -2,12 +2,18 @@ import { Serie, Options } from '@chartwerk/core';
import { AxisRange } from '@chartwerk/core/dist/types'; import { AxisRange } from '@chartwerk/core/dist/types';
type LineTimeSerieParams = { type LineTimeSerieParams = {
maxLength: number, maxLength: number;
renderDots: boolean, renderDots: boolean;
renderLines: boolean, // TODO: refactor same as scatter-pod renderLines: boolean; // TODO: refactor same as scatter-pod
dashArray: string; // dasharray attr, only for lines dashArray: string; // dasharray attr, only for lines
class: string; // option to add custom class to each serie element class: string; // option to add custom class to each serie element
renderArea: boolean; // TODO: move to render type renderArea: AreaType; // default is none
}
export enum AreaType {
NONE = 'None',
ABOVE = 'Above',
BELOW = 'Below',
} }
export type LineTimeSerie = Serie & Partial<LineTimeSerieParams>; export type LineTimeSerie = Serie & Partial<LineTimeSerieParams>;

Loading…
Cancel
Save