Browse Source

segment select

pull/63/head
glitch4347 6 months ago
parent
commit
bf3aab2db1
  1. 12
      examples/segments.html
  2. 42
      src/components/segments.ts
  3. 2
      src/index.ts
  4. 7
      src/models/segment.ts

12
examples/segments.html

@ -13,7 +13,7 @@
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 segmentsData = [3, 6, 9].map(el => [startTime + el * 1000, startTime + (el + 1) * 1000]); const segmentsData = [3, 6, 9].map(el => [startTime + el * 1000, startTime + (el + 1) * 1100]);
let options = { let options = {
renderLegend: false, renderLegend: false,
axis: { axis: {
@ -27,9 +27,15 @@
{ datapoints: timeSerieData, color: 'black' }, { datapoints: timeSerieData, color: 'black' },
], ],
options, options,
[], undefined,
[ [
{ data: segmentsData, color:'#FFE545' } {
data: segmentsData,
color:'#FFE545',
select: true,
onSelect: console.log,
onUnselect: console.log
}
] ]
); );
pod.render(); pod.render();

42
src/components/segments.ts

@ -1,34 +1,40 @@
import { SegmentSerie } from "../models/segment"; import { SegmentSerie, SegmentElement } from "../models/segment";
import { PodState } from "@chartwerk/core"; import { PodState } from "@chartwerk/core";
import { LineTimeSerie, LineOptions } from "../types"; import { LineTimeSerie, LineOptions } from "../types";
import d3 from "d3"; import * as d3 from "d3";
export class Segments { export class Segments {
// TODO: more semantic name // TODO: more semantic name
private _d3Holder = null; private _d3Holder = null;
private _metricCon = null;
constructor(private _series: SegmentSerie[], private _state: PodState<LineTimeSerie, LineOptions>) { constructor(
private _series: SegmentSerie[],
private _state: PodState<LineTimeSerie, LineOptions>
) {
} }
render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>) { render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>, chartContainer: d3.Selection<SVGGElement, unknown, null, undefined>) {
if(this._d3Holder !== null) { if(this._d3Holder !== null) {
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 s of this._series) { for (const s of this._series) {
this.renderSerie(s); this.renderSerie(chartContainer, s);
} }
} }
protected renderSerie(serie: SegmentSerie) { protected renderSerie(chartContainer: d3.Selection<SVGGElement, unknown, null, undefined>, serie: SegmentSerie) {
// TODO: it's hack with core, need to find a better way
const overlay = chartContainer.select('.overlay');
serie.data.forEach((d) => { serie.data.forEach((d) => {
// @ts-ignore // @ts-ignore
const startPositionX = this._state.xScale(d[0]) as number; const startPositionX = this._state.xScale(d[0]) as number;
// @ts-ignore // @ts-ignore
const endPositionX = this._state.xScale(d[1]) as number; const endPositionX = this._state.xScale(d[1]) as number;
const width = endPositionX - startPositionX // Math.max(endPositionX - startPositionX, MIMIMUM_SEGMENT_WIDTH); const width = endPositionX - startPositionX // Math.max(endPositionX - startPositionX, MIMIMUM_SEGMENT_WIDTH);
this._d3Holder.append('rect') this._d3Holder.append('rect')
.attr('class', 'segment') .attr('class', 'segment')
.attr('x', startPositionX) .attr('x', startPositionX)
@ -38,8 +44,26 @@ export class Segments {
.attr('height', this._state.boxParams.height) .attr('height', this._state.boxParams.height)
.attr('opacity', 0.3) .attr('opacity', 0.3)
.style('fill', serie.color) .style('fill', serie.color)
.style('pointer-events', 'none'); .on('mouseover', function() {
if(serie.select === true) {
d3.select(this).attr('opacity', 0.5);
if(serie.onSelect) {
serie.onSelect(d);
}
}
})
.on('mouseout', function(e) {
if(serie.select === true) {
d3.select(this).attr('opacity', 0.3);
if(serie.onUnselect) {
serie.onUnselect(d);
}
}
})
.on('mousemove', function(e) {
var event = new MouseEvent('mousemove', d3.event);
overlay.node().dispatchEvent(event)
})
}); });
} }
} }

2
src/index.ts

@ -56,7 +56,7 @@ class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
} }
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, this.chartContainer);
} }
clearAllMetrics(): void { clearAllMetrics(): void {

7
src/models/segment.ts

@ -1,4 +1,9 @@
export type SegmentElement = [number, number, any?];
export type SegmentSerie = { export type SegmentSerie = {
color: string; color: string;
data: [number, number, any?][] // [from, to, payload?] payload is any data for tooltip data: SegmentElement[] // [from, to, payload?] payload is any data for tooltip,
select?: boolean,
onSelect?: (SegmentElement) => void
onUnselect?: (SegmentElement) => void
} }
Loading…
Cancel
Save