From bf3aab2db1ce3fe58dfbbffac7896c41fc4a1916 Mon Sep 17 00:00:00 2001 From: glitch4347 Date: Fri, 17 May 2024 11:47:13 +0200 Subject: [PATCH 1/2] segment select --- examples/segments.html | 12 ++++++++--- src/components/segments.ts | 42 ++++++++++++++++++++++++++++++-------- src/index.ts | 2 +- src/models/segment.ts | 7 ++++++- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/examples/segments.html b/examples/segments.html index 7ad8a25..cf10640 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,15 @@ { datapoints: timeSerieData, color: 'black' }, ], options, - [], + undefined, [ - { data: segmentsData, color:'#FFE545' } + { + data: segmentsData, + color:'#FFE545', + select: true, + onSelect: console.log, + onUnselect: console.log + } ] ); pod.render(); diff --git a/src/components/segments.ts b/src/components/segments.ts index c3de5c8..ef76ca1 100644 --- a/src/components/segments.ts +++ b/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 { LineTimeSerie, LineOptions } from "../types"; -import d3 from "d3"; +import * as d3 from "d3"; 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); - + this._d3Holder.append('rect') .attr('class', 'segment') .attr('x', startPositionX) @@ -38,8 +44,26 @@ export class Segments { .attr('height', this._state.boxParams.height) .attr('opacity', 0.3) .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) + }) }); - } } \ 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..1a0e086 100644 --- a/src/models/segment.ts +++ b/src/models/segment.ts @@ -1,4 +1,9 @@ +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, + onSelect?: (SegmentElement) => void + onUnselect?: (SegmentElement) => void } \ No newline at end of file From 04a01b75a148600df8f8483f0742333b60bb2378 Mon Sep 17 00:00:00 2001 From: glitch4347 Date: Fri, 17 May 2024 12:56:42 +0200 Subject: [PATCH 2/2] opacity param --- examples/segments.html | 5 +--- examples/segments_select.html | 46 +++++++++++++++++++++++++++++++++++ src/components/segments.ts | 12 ++++++--- src/models/segment.ts | 2 ++ 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 examples/segments_select.html diff --git a/examples/segments.html b/examples/segments.html index cf10640..8938eba 100644 --- a/examples/segments.html +++ b/examples/segments.html @@ -31,10 +31,7 @@ [ { data: segmentsData, - color:'#FFE545', - select: true, - onSelect: console.log, - onUnselect: console.log + color:'#FFE545' } ] ); 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 ef76ca1..e8c5298 100644 --- a/src/components/segments.ts +++ b/src/components/segments.ts @@ -4,6 +4,9 @@ import { LineTimeSerie, LineOptions } from "../types"; import * as d3 from "d3"; +const OPACITY = 0.3; +const OPACITY_SELECT = 0.3; + export class Segments { // TODO: more semantic name private _d3Holder = null; @@ -34,7 +37,8 @@ export class Segments { // @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) @@ -42,11 +46,11 @@ 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) .on('mouseover', function() { if(serie.select === true) { - d3.select(this).attr('opacity', 0.5); + d3.select(this).attr('opacity', opacitySelect); if(serie.onSelect) { serie.onSelect(d); } @@ -54,7 +58,7 @@ export class Segments { }) .on('mouseout', function(e) { if(serie.select === true) { - d3.select(this).attr('opacity', 0.3); + d3.select(this).attr('opacity', opacity); if(serie.onUnselect) { serie.onUnselect(d); } diff --git a/src/models/segment.ts b/src/models/segment.ts index 1a0e086..12557a1 100644 --- a/src/models/segment.ts +++ b/src/models/segment.ts @@ -4,6 +4,8 @@ export type SegmentSerie = { color: string; 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