react-component-marker-and-segment-feature-#28 #33

Merged
rozetko merged 8 commits from react-component-marker-and-segment-feature-#28 into main 12 months ago
  1. 5
      examples/markers.html
  2. 62
      react/ChartwerkLinePod.tsx
  3. 2
      src/components/markers.ts
  4. 9
      src/index.ts
  5. 3
      src/models/marker.ts

5
examples/markers.html

@ -13,8 +13,9 @@
const startTime = 1701790172908; const startTime = 1701790172908;
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8] const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8]
.map((el, idx) => [startTime + idx * 1000, el]); .map((el, idx) => [startTime + idx * 1000, el]);
const markersData1 = [3, 6, 9].map(el => startTime + el * 1000); // TODO: make this one-dimensinal data when implemented
const markersData2 = [4, 11].map(el => startTime + el * 1000); const markersData1 = [3, 6, 9].map(el => [startTime + el * 1000]);
const markersData2 = [4, 11].map(el => [startTime + el * 1000]);
let options = { let options = {
renderLegend: false, renderLegend: false,
axis: { axis: {

62
react/ChartwerkLinePod.tsx

@ -1,15 +1,20 @@
import type { LineTimeSerie, LineOptions } from '@chartwerk/line-pod'; import { LineTimeSerie, LineOptions, LinePod } from '@chartwerk/line-pod';
import { LinePod } from '@chartwerk/line-pod';
import { useEffect, useRef, useState, PropsWithChildren, forwardRef } from 'react'; import { AxisRange } from '@chartwerk/core/dist/types';
import { MarkerSerie } from '@chartwerk/line-pod/dist/models/marker';
import { SegmentSerie } from '@chartwerk/line-pod/dist/models/segment';
import { useEffect, useRef, useState } from 'react';
import _ from 'lodash';
import * as _ from 'lodash';
export type AxisRange = [number, number] | undefined;
export type ChartwerkLinePodProps = { export type ChartwerkLinePodProps = {
id: string; id?: string;
series: LineTimeSerie[]; series: LineTimeSerie[];
options: LineOptions; options?: LineOptions;
markers?: MarkerSerie[],
segments?: SegmentSerie[],
className?: string; className?: string;
// TODO: callback types should be exported from chartwerk // TODO: callback types should be exported from chartwerk
onZoomIn?: (ranges: AxisRange[]) => void; onZoomIn?: (ranges: AxisRange[]) => void;
@ -25,7 +30,8 @@ export type ChartwerkLinePodProps = {
onRenderEnd?: () => void, onRenderEnd?: () => void,
} }
export const ChartwerkLinePod = forwardRef<HTMLDivElement, PropsWithChildren<ChartwerkLinePodProps>>((props, ref) => { export function ChartwerkLinePod(props: ChartwerkLinePodProps) {
const [pod, setPod] = useState<LinePod | null>(null); const [pod, setPod] = useState<LinePod | null>(null);
const [hack, setHack] = useState<number | null>(null); const [hack, setHack] = useState<number | null>(null);
@ -35,23 +41,16 @@ export const ChartwerkLinePod = forwardRef<HTMLDivElement, PropsWithChildren<Cha
useEffect(() => { useEffect(() => {
// this function will be called on component unmount // this function will be called on component unmount
return () => { return () => {
if (pod === null) { if(pod === null) { return; }
return;
}
console.log('remove chart');
// @ts-ignore // @ts-ignore
pod.removeEventListeners(); pod.removeEventListeners();
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
if (chart === null) { if(chart === null) { return; }
return;
}
let eventsCallbacks = _.cloneDeep(props.options.eventsCallbacks || {}); let eventsCallbacks = _.cloneDeep(props.options?.eventsCallbacks || {});
if (props.onZoomIn) { if (props.onZoomIn) {
eventsCallbacks.zoomIn = props.onZoomIn; eventsCallbacks.zoomIn = props.onZoomIn;
} }
@ -83,39 +82,36 @@ export const ChartwerkLinePod = forwardRef<HTMLDivElement, PropsWithChildren<Cha
eventsCallbacks.renderStart = props.onRenderStart; eventsCallbacks.renderStart = props.onRenderStart;
} }
if (pod === null) { if(pod === null) {
console.log('create chart');
const newPod = new LinePod( const newPod = new LinePod(
// @ts-ignore // @ts-ignore
chart, chart,
props.series, props.series,
{ {
...props.options, ...props.options,
eventsCallbacks, eventsCallbacks
} },
props.markers,
props.segments
); );
setPod(newPod); setPod(newPod);
newPod.render(); newPod.render();
} else { } else {
pod.updateData(props.series, { pod.updateData(props.series, props.options);
...props.options,
eventsCallbacks,
});
} }
}, [chart, pod, props.id, props.series, props.options]); }, [chart, pod, props.id, props.options, props.markers, 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(() => {
if (hack === null) { if(hack === null) {
setHack(1); setHack(1);
} }
}, 1); }, 1);
return ( return (
<div ref={ref}>
<div id={props.id} className={props.className} ref={chartRef}></div> <div id={props.id} className={props.className} ref={chartRef}></div>
{props.children}
</div>
); );
}); }
export default ChartwerkLinePod;

2
src/components/markers.ts

@ -23,7 +23,7 @@ export class Markers {
protected renderSerie(serie: MarkerSerie) { protected renderSerie(serie: MarkerSerie) {
serie.data.forEach((d) => { serie.data.forEach((d) => {
let linePosition = this._state.xScale(d) as number; let linePosition = this._state.xScale(d[0]) as number;
this._d3Holder.append('line') this._d3Holder.append('line')
.attr('class', 'gap-line') .attr('class', 'gap-line')
.attr('stroke', serie.color) .attr('stroke', serie.color)

9
src/index.ts

@ -13,7 +13,8 @@ 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;
export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
lineGenerator = null; lineGenerator = null;
areaGenerator = null; areaGenerator = null;
lineGeneratorY1 = null; lineGeneratorY1 = null;
@ -23,7 +24,9 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
private _segmentsLayer: Segments = null; private _segmentsLayer: Segments = null;
constructor( constructor(
_el: HTMLElement, _series: LineTimeSerie[] = [], _options: LineOptions = {}, _el: HTMLElement,
_series: LineTimeSerie[] = [],
_options: LineOptions = {},
private _markerSeries = [], private _markerSeries = [],
private _segmentSeries = [], private _segmentSeries = [],
) { ) {
@ -432,4 +435,4 @@ export const VueChartwerkLinePod = {
} }
}; };
export { LineTimeSerie, LineOptions, TimeFormat }; export { LineTimeSerie, LineOptions, TimeFormat, LinePod };

3
src/models/marker.ts

@ -1,4 +1,5 @@
export type MarkerSerie = { export type MarkerSerie = {
color: string; color: string;
data: [number, number, any][] // [x, y, payload] payload is any data for tooltip // TODO: make one-dimensional array with only x
data: [number, any?][] // [x, payload] payload is any data for tooltip
} }

Loading…
Cancel
Save