Browse Source

Merge pull request 'marker-callback-#25' (#35) from marker-callback-#25 into main

Reviewed-on: #35
pull/37/head
Coin de Gamma 11 months ago
parent
commit
b8cd14e4b8
  1. 4
      examples/markers.html
  2. 47
      examples/markers_select.html
  3. 8
      react/ChartwerkLinePod.tsx
  4. 18
      src/components/markers.ts
  5. 8
      src/index.ts
  6. 12
      src/models/marker.ts

4
examples/markers.html

@ -29,10 +29,12 @@
{ datapoints: timeSerieData, color: 'black' }, { datapoints: timeSerieData, color: 'black' },
], ],
options, options,
[ {
series: [
{ data: markersData1, color: 'red' }, { data: markersData1, color: 'red' },
{ data: markersData2, color: 'blue' }, { data: markersData2, color: 'blue' },
] ]
}
); );
pod.render(); pod.render();
</script> </script>

47
examples/markers_select.html

@ -0,0 +1,47 @@
<!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]);
// TODO: make this one-dimensinal data when implemented
const markersData = [3, 6, 9].map(el => [
startTime + el * 1000,
{ el }
]);
let options = {
renderLegend: false,
axis: {
y: { range: [0, 10] },
x: { format: 'time' }
},
}
var pod = new LinePod(
document.getElementById('chart'),
[
{ datapoints: timeSerieData, color: 'black' },
],
options,
{
series: [
{ data: markersData, color: 'red' },
],
events: {
onMouseMove: (el) => { console.log(el); },
onMouseOut: () => { console.log('mouse out'); }
}
}
);
pod.render();
</script>
</body>
</html>

8
react/ChartwerkLinePod.tsx

@ -1,7 +1,7 @@
import { LineTimeSerie, LineOptions, LinePod } from '@chartwerk/line-pod'; import { LineTimeSerie, LineOptions, LinePod } from '@chartwerk/line-pod';
import { AxisRange } from '@chartwerk/core/dist/types'; import { AxisRange } from '@chartwerk/core/dist/types';
import { MarkerSerie } from '@chartwerk/line-pod/dist/models/marker'; import { MarkersConf } from '@chartwerk/line-pod/dist/models/marker';
import { SegmentSerie } from '@chartwerk/line-pod/dist/models/segment'; import { SegmentSerie } from '@chartwerk/line-pod/dist/models/segment';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
@ -13,7 +13,7 @@ export type ChartwerkLinePodProps = {
id?: string; id?: string;
series: LineTimeSerie[]; series: LineTimeSerie[];
options?: LineOptions; options?: LineOptions;
markers?: MarkerSerie[], markersConf?: MarkersConf,
segments?: SegmentSerie[], segments?: SegmentSerie[],
className?: string; className?: string;
// TODO: callback types should be exported from chartwerk // TODO: callback types should be exported from chartwerk
@ -91,7 +91,7 @@ export function ChartwerkLinePod(props: ChartwerkLinePodProps) {
...props.options, ...props.options,
eventsCallbacks eventsCallbacks
}, },
props.markers, props.markersConf,
props.segments props.segments
); );
setPod(newPod); setPod(newPod);
@ -99,7 +99,7 @@ export function ChartwerkLinePod(props: ChartwerkLinePodProps) {
} else { } else {
pod.updateData(props.series, props.options); pod.updateData(props.series, props.options);
} }
}, [chart, pod, props.id, props.options, props.markers, props.segments]); }, [chart, pod, props.id, props.options, props.markersConf, props.segments]);
// TODO: it's a hack to render the LinePod right after the div appears in DOM // TODO: it's a hack to render the LinePod right after the div appears in DOM
setTimeout(() => { setTimeout(() => {

18
src/components/markers.ts

@ -1,4 +1,4 @@
import { MarkerSerie } from "../models/marker"; import { MarkersConf, MarkerSerie } from "../models/marker";
import { PodState } from "@chartwerk/core"; import { PodState } from "@chartwerk/core";
import { LineTimeSerie, LineOptions } from "../types"; import { LineTimeSerie, LineOptions } from "../types";
@ -8,7 +8,8 @@ export class Markers {
// TODO: more semantic name // TODO: more semantic name
private _d3Holder = null; private _d3Holder = null;
constructor(private _markers: MarkerSerie[], private _state: PodState<LineTimeSerie, LineOptions>) { constructor(private _markerConf: MarkersConf, private _state: PodState<LineTimeSerie, LineOptions>) {
} }
render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>) { render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>) {
@ -16,7 +17,7 @@ export class Markers {
this._d3Holder.remove(); this._d3Holder.remove();
} }
this._d3Holder = metricContainer.append('g').attr('class', 'markers-layer'); this._d3Holder = metricContainer.append('g').attr('class', 'markers-layer');
for (const ms of this._markers) { for (const ms of this._markerConf.series) {
this.renderSerie(ms); this.renderSerie(ms);
} }
} }
@ -36,15 +37,22 @@ export class Markers {
// @ts-ignore // TODO: remove ignore but boxParams are protected // @ts-ignore // TODO: remove ignore but boxParams are protected
.attr('y2', this._state.boxParams.height) .attr('y2', this._state.boxParams.height)
.attr('pointer-events', 'none'); .attr('pointer-events', 'none');
this._d3Holder.append('circle') let circle = this._d3Holder.append('circle')
.attr('class', 'gap-circle') .attr('class', 'gap-circle')
.attr('stroke', serie.color) .attr('stroke', serie.color)
.attr('stroke-width', '2px') .attr('stroke-width', '2px')
.attr('r', 4) .attr('r', 4)
.attr('cx', linePosition) .attr('cx', linePosition)
.attr('cy', 5) .attr('cy', 5)
.attr('pointer-events', 'none') // TODO: make all on implementation of Events
if(this._markerConf !== undefined) {
circle
.attr('pointer-events', 'all')
.style('cursor', 'pointer') .style('cursor', 'pointer')
.on('mousemove', () => this._markerConf.events.onMouseMove(d))
.on('mouseout', () => this._markerConf.events.onMouseOut())
}
}); });
} }

8
src/index.ts

@ -4,6 +4,7 @@ import { Markers } from './components/markers';
import { Segments } from './components/segments'; import { Segments } from './components/segments';
import { LineSeries } from './models/line_series'; import { LineSeries } from './models/line_series';
import { MarkersConf } from './models/marker';
import * as d3 from 'd3'; import * as d3 from 'd3';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -27,7 +28,7 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
_el: HTMLElement, _el: HTMLElement,
_series: LineTimeSerie[] = [], _series: LineTimeSerie[] = [],
_options: LineOptions = {}, _options: LineOptions = {},
private _markerSeries = [], private _markersConf?: MarkersConf,
private _segmentSeries = [], private _segmentSeries = [],
) { ) {
super(_el, _series, _options); super(_el, _series, _options);
@ -48,8 +49,11 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
for(const serie of this.series.visibleSeries) { for(const serie of this.series.visibleSeries) {
this._renderMetric(serie); this._renderMetric(serie);
} }
this._markersLayer = new Markers(this._markerSeries, this.state); if(this._markersConf !== undefined) {
this._markersLayer = new Markers(this._markersConf, this.state);
this._markersLayer.render(this.metricContainer); this._markersLayer.render(this.metricContainer);
}
this._segmentsLayer = new Segments(this._segmentSeries, this.state); this._segmentsLayer = new Segments(this._segmentSeries, this.state);
this._segmentsLayer.render(this.metricContainer); this._segmentsLayer.render(this.metricContainer);
} }

12
src/models/marker.ts

@ -1,5 +1,15 @@
export type MarkerElem = [number, any?];
export type MarkerSerie = { export type MarkerSerie = {
color: string; color: string;
// TODO: make one-dimensional array with only x // TODO: make one-dimensional array with only x
data: [number, any?][] // [x, payload] payload is any data for tooltip data: MarkerElem[] // [x, payload] payload is any data for tooltip
}
export type MarkersConf = {
series: MarkerSerie[],
events?: {
onMouseMove?: (el: MarkerElem) => void;
onMouseOut?: () => void;
}
} }

Loading…
Cancel
Save