rozetko
12 months ago
5 changed files with 105 additions and 3 deletions
@ -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: 100%; height: 500px;"></div> |
||||||
|
|
||||||
|
<script type="text/javascript"> |
||||||
|
const startTime = 1701790172908; |
||||||
|
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8] |
||||||
|
.map((el, idx) => [startTime + idx * 1000, el]); |
||||||
|
const markersData1 = [3, 6, 9].map(el => startTime + el * 1000); |
||||||
|
const markersData2 = [4, 11].map(el => startTime + el * 1000); |
||||||
|
let options = { |
||||||
|
renderLegend: false, |
||||||
|
axis: { |
||||||
|
y: { range: [0, 10] }, |
||||||
|
x: { format: 'time' } |
||||||
|
}, |
||||||
|
} |
||||||
|
var pod = new LinePod( |
||||||
|
document.getElementById('chart'), |
||||||
|
[ |
||||||
|
{ datapoints: timeSerieData, color: 'black' }, |
||||||
|
], |
||||||
|
options, |
||||||
|
[ |
||||||
|
{ data: markersData1, color: 'red' }, |
||||||
|
{ data: markersData2, color: 'blue' }, |
||||||
|
] |
||||||
|
); |
||||||
|
pod.render(); |
||||||
|
</script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,51 @@ |
|||||||
|
import { MarkerSerie } from "../models/marker"; |
||||||
|
import { PodState } from "@chartwerk/core"; |
||||||
|
import { LineTimeSerie, LineOptions } from "../types"; |
||||||
|
|
||||||
|
import d3 from "d3"; |
||||||
|
|
||||||
|
export class Markers { |
||||||
|
// TODO: more sentic name
|
||||||
|
private _d3Holder = null; |
||||||
|
|
||||||
|
constructor(private _markers: MarkerSerie[], private _state: PodState<LineTimeSerie, LineOptions>) { |
||||||
|
} |
||||||
|
|
||||||
|
render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>) { |
||||||
|
if(this._d3Holder !== null) { |
||||||
|
this._d3Holder.remove(); |
||||||
|
} |
||||||
|
this._d3Holder = metricContainer.append('g').attr('class', 'markers-layer'); |
||||||
|
for (const ms of this._markers) { |
||||||
|
this.renderMarkerSerie(ms); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected renderMarkerSerie(serie: MarkerSerie) { |
||||||
|
serie.data.forEach((d) => { |
||||||
|
let linePosition = this._state.xScale(d) as number; |
||||||
|
this._d3Holder.append('line') |
||||||
|
.attr('class', 'gap-line') |
||||||
|
.attr('stroke', serie.color) |
||||||
|
.attr('stroke-width', '1px') |
||||||
|
.attr('stroke-opacity', '0.3') |
||||||
|
.attr('stroke-dasharray', '4') |
||||||
|
.attr('x1', linePosition) |
||||||
|
.attr('x2', linePosition) |
||||||
|
.attr('y1', 0) |
||||||
|
// @ts-ignore // TODO: remove ignore but boxParams are protected
|
||||||
|
.attr('y2', this._state.boxParams.height) |
||||||
|
.attr('pointer-events', 'none'); |
||||||
|
this._d3Holder.append('circle') |
||||||
|
.attr('class', 'gap-circle') |
||||||
|
.attr('stroke', serie.color) |
||||||
|
.attr('stroke-width', '2px') |
||||||
|
.attr('r', 4) |
||||||
|
.attr('cx', linePosition) |
||||||
|
.attr('cy', 5) |
||||||
|
.attr('pointer-events', 'none') // TODO: make all on implementation of Events
|
||||||
|
.style('cursor', 'pointer') |
||||||
|
}); |
||||||
|
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue