Compare commits

..

3 Commits

  1. 39
      examples/area.html
  2. 71
      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>

71
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<LineTimeSerie, LineOptions> {
lineGenerator = null;
areaGenerator = null;
lineGeneratorY1 = null;
areaGeneratorY1 = null;
private _markersLayer: Markers = null;
private _segmentsLayer: Segments = null;
@ -40,15 +35,14 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
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<LineTimeSerie, LineOptions> {
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<LineTimeSerie, LineOptions> {
.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<LineTimeSerie, LineOptions> {
.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 };

4
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,
};

14
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<LineTimeSerieParams>;

Loading…
Cancel
Save