diff --git a/examples/segments.html b/examples/segments.html index 7ad8a25..8938eba 100644 --- a/examples/segments.html +++ b/examples/segments.html @@ -13,7 +13,7 @@ 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 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 = { renderLegend: false, axis: { @@ -27,9 +27,12 @@ { datapoints: timeSerieData, color: 'black' }, ], options, - [], + undefined, [ - { data: segmentsData, color:'#FFE545' } + { + data: segmentsData, + color:'#FFE545' + } ] ); pod.render(); diff --git a/examples/segments_select.html b/examples/segments_select.html new file mode 100644 index 0000000..774704c --- /dev/null +++ b/examples/segments_select.html @@ -0,0 +1,46 @@ + + + + + + + + + +
+ + + + diff --git a/src/components/segments.ts b/src/components/segments.ts index c3de5c8..e8c5298 100644 --- a/src/components/segments.ts +++ b/src/components/segments.ts @@ -1,34 +1,44 @@ -import { SegmentSerie } from "../models/segment"; +import { SegmentSerie, SegmentElement } from "../models/segment"; import { PodState } from "@chartwerk/core"; import { LineTimeSerie, LineOptions } from "../types"; -import d3 from "d3"; +import * as d3 from "d3"; + +const OPACITY = 0.3; +const OPACITY_SELECT = 0.3; export class Segments { // TODO: more semantic name private _d3Holder = null; + private _metricCon = null; - constructor(private _series: SegmentSerie[], private _state: PodState) { + constructor( + private _series: SegmentSerie[], + private _state: PodState + ) { } - render(metricContainer: d3.Selection) { + render(metricContainer: d3.Selection, chartContainer: d3.Selection) { if(this._d3Holder !== null) { this._d3Holder.remove(); } this._d3Holder = metricContainer.append('g').attr('class', 'markers-layer'); for (const s of this._series) { - this.renderSerie(s); + this.renderSerie(chartContainer, s); } } - protected renderSerie(serie: SegmentSerie) { + protected renderSerie(chartContainer: d3.Selection, serie: SegmentSerie) { + // TODO: it's hack with core, need to find a better way + const overlay = chartContainer.select('.overlay'); serie.data.forEach((d) => { // @ts-ignore const startPositionX = this._state.xScale(d[0]) as number; // @ts-ignore const endPositionX = this._state.xScale(d[1]) as number; const width = endPositionX - startPositionX // Math.max(endPositionX - startPositionX, MIMIMUM_SEGMENT_WIDTH); - + const opacity = serie.opacity || OPACITY; + const opacitySelect = serie.opacitySelect || OPACITY_SELECT; this._d3Holder.append('rect') .attr('class', 'segment') .attr('x', startPositionX) @@ -36,10 +46,28 @@ export class Segments { .attr('width', width) // @ts-ignore // TODO: remove ignore but boxParams are protected .attr('height', this._state.boxParams.height) - .attr('opacity', 0.3) + .attr('opacity', opacity) .style('fill', serie.color) - .style('pointer-events', 'none'); + .on('mouseover', function() { + if(serie.select === true) { + d3.select(this).attr('opacity', opacitySelect); + if(serie.onSelect) { + serie.onSelect(d); + } + } + }) + .on('mouseout', function(e) { + if(serie.select === true) { + d3.select(this).attr('opacity', opacity); + if(serie.onUnselect) { + serie.onUnselect(d); + } + } + }) + .on('mousemove', function(e) { + var event = new MouseEvent('mousemove', d3.event); + overlay.node().dispatchEvent(event) + }) }); - } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 5a26d95..4a2f291 100644 --- a/src/index.ts +++ b/src/index.ts @@ -56,7 +56,7 @@ class LinePod extends ChartwerkPod { } this._segmentsLayer = new Segments(this._segmentSeries, this.state); - this._segmentsLayer.render(this.metricContainer); + this._segmentsLayer.render(this.metricContainer, this.chartContainer); } clearAllMetrics(): void { diff --git a/src/models/segment.ts b/src/models/segment.ts index 39db4f8..12557a1 100644 --- a/src/models/segment.ts +++ b/src/models/segment.ts @@ -1,4 +1,11 @@ +export type SegmentElement = [number, number, any?]; + export type SegmentSerie = { 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, + opacity?: number, + opacitySelect?: number, + onSelect?: (SegmentElement) => void + onUnselect?: (SegmentElement) => void } \ No newline at end of file