diff --git a/examples/area.html b/examples/area.html
new file mode 100644
index 0000000..67082dd
--- /dev/null
+++ b/examples/area.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/index.ts b/src/index.ts
index 27e0c59..84f67f3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,5 @@
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 { Segments } from './components/segments';
@@ -14,14 +14,9 @@ const METRIC_CIRCLE_RADIUS = 1.5;
const CROSSHAIR_CIRCLE_RADIUS = 3;
const CROSSHAIR_BACKGROUND_RAIDUS = 9;
const CROSSHAIR_BACKGROUND_OPACITY = 0.3;
-
+type Generator = d3.Line<[number, number]> | d3.Area<[number, number]>;
class LinePod extends ChartwerkPod {
- lineGenerator = null;
- areaGenerator = null;
- lineGeneratorY1 = null;
- areaGeneratorY1 = null;
-
private _markersLayer: Markers = null;
private _segmentsLayer: Segments = null;
@@ -40,15 +35,14 @@ class LinePod extends ChartwerkPod {
this.clearAllMetrics();
this.updateCrosshair();
- this.initLineGenerator();
- this.initAreaGenerator();
if(!this.series.isSeriesAvailable) {
this.renderNoDataPointsMessage();
return;
}
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) {
this._markersLayer = new Markers(this.d3Node, this._markersConf, this.state, this.margin);
@@ -65,31 +59,28 @@ class LinePod extends ChartwerkPod {
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 {
- this.areaGenerator = d3.area()
- .x(d => this.state.xScale(d[0]))
- .y1(d => this.state.yScale(d[1]))
- .y0(d => this.height);
- this.areaGeneratorY1 = d3.area()
- .x(d => this.state.xScale(d[0]))
- .y1(d => this.state.y1Scale(d[1]))
- .y0(d => this.height);
- }
- getRenderGenerator(renderArea: boolean, yOrientation: yAxisOrientation): any {
- if(renderArea) {
- return yOrientation === yAxisOrientation.LEFT ? this.areaGenerator : this.areaGeneratorY1;
+ getRenderGenerator(renderArea: AreaType, yOrientation: yAxisOrientation): Generator {
+ 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]))
+ .y(d => yScale(d[1]));
+ case AreaType.ABOVE:
+ return d3.area()
+ .x(d => this.state.xScale(d[0]))
+ .y0(this.height)
+ .y1(d => yScale(d[1]));
+ case AreaType.BELOW:
+ return d3.area()
+ .x(d => this.state.xScale(d[0]))
+ .y0(d => yScale(d[1]))
+ .y1(0);
+ default:
+ throw new Error(`Unknown type of renderArea: ${renderArea}`);
}
- return yOrientation === yAxisOrientation.LEFT ? this.lineGenerator : this.lineGeneratorY1;
}
_renderDots(serie: LineTimeSerie): void {
@@ -105,9 +96,9 @@ class LinePod extends ChartwerkPod {
.attr('cy', d => this.state.getYScaleByOrientation(serie.yOrientation)(d[1]));
}
- _renderLines(serie: LineTimeSerie): void {
- const fillColor = serie.renderArea ? serie.color : 'none';
- const fillOpacity = serie.renderArea ? 0.5 : 'none';
+ _renderLines(serie: LineTimeSerie, generator: Generator): void {
+ const fillColor = serie.renderArea !== AreaType.NONE ? serie.color : 'none';
+ const fillOpacity = serie.renderArea !== AreaType.NONE ? 0.5 : 'none';
this.metricContainer
.append('path')
@@ -120,12 +111,12 @@ class LinePod extends ChartwerkPod {
.attr('stroke-opacity', 0.7)
.attr('pointer-events', 'none')
.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) {
- this._renderLines(serie);
+ this._renderLines(serie, generator);
}
if(serie.renderDots === true) {
@@ -490,4 +481,4 @@ export const VueChartwerkLinePod = {
}
};
-export { LineTimeSerie, LineOptions, TimeFormat, LinePod };
+export { LineTimeSerie, LineOptions, TimeFormat, LinePod, AreaType };
diff --git a/src/models/line_series.ts b/src/models/line_series.ts
index d75cf07..55737ef 100644
--- a/src/models/line_series.ts
+++ b/src/models/line_series.ts
@@ -1,5 +1,5 @@
import { CoreSeries, yAxisOrientation } from '@chartwerk/core';
-import { LineTimeSerie } from '../types';
+import { LineTimeSerie, AreaType } from '../types';
import * as _ from 'lodash';
@@ -10,7 +10,7 @@ const LINE_SERIE_DEFAULTS = {
renderLines: true,
dashArray: '0',
class: '',
- renderArea: false,
+ renderArea: AreaType.NONE,
yOrientation: yAxisOrientation.LEFT,
};
diff --git a/src/types.ts b/src/types.ts
index 5e172ea..a67e1d4 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -2,12 +2,18 @@ import { Serie, Options } from '@chartwerk/core';
import { AxisRange } from '@chartwerk/core/dist/types';
type LineTimeSerieParams = {
- maxLength: number,
- renderDots: boolean,
- renderLines: boolean, // TODO: refactor same as scatter-pod
+ maxLength: number;
+ renderDots: boolean;
+ renderLines: boolean; // TODO: refactor same as scatter-pod
dashArray: string; // dasharray attr, only for lines
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;