From 8d228ccb3c73d821a524a1722f5179eb8c3e495f Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Thu, 10 Aug 2023 01:14:57 +0200 Subject: [PATCH 1/7] Implement adaptive selectZoom --- src/plugins_extra/selectZoom.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index dcfcf8e..c006ba1 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -5,6 +5,8 @@ export interface SelectZoomOptions { mouseButtons: number; enableX: boolean; enableY: boolean; + thresholdX: number; + thresholdY: number; cancelOnSecondPointer: boolean; } @@ -12,6 +14,8 @@ const defaultOptions = { mouseButtons: 1, enableX: true, enableY: true, + thresholdX: 0, + thresholdY: 0, cancelOnSecondPointer: false, } as const; @@ -95,9 +99,12 @@ export class SelectZoom { return; const p = this.getPoint(ev); - if (this.options.enableX) { - const x = Math.min(this.start.p.x, p.x); - const w = Math.abs(this.start.p.x - p.x); + const x = Math.min(this.start.p.x, p.x); + const w = Math.abs(this.start.p.x - p.x); + const y = Math.min(this.start.p.y, p.y); + const h = Math.abs(this.start.p.y - p.y); + + if (this.options.enableX && ((w >= h) || (w >= this.options.thresholdX))) { this.visual.x.baseVal.value = x; this.visual.width.baseVal.value = w; } else { @@ -105,9 +112,7 @@ export class SelectZoom { this.visual.setAttribute('width', '100%'); } - if (this.options.enableY) { - const y = Math.min(this.start.p.y, p.y); - const h = Math.abs(this.start.p.y - p.y); + if (this.options.enableY && ((h > w) || (h >= this.options.thresholdY))) { this.visual.y.baseVal.value = y; this.visual.height.baseVal.value = h; } else { @@ -126,7 +131,7 @@ export class SelectZoom { if (this.options.enableX) { const x1 = Math.min(this.start.p.x, p.x); const x2 = Math.max(this.start.p.x, p.x); - if (x2 - x1 > 0) { + if (x2 - x1 > this.options.thresholdX) { const newDomain = [ this.chart.model.xScale.invert(x1), this.chart.model.xScale.invert(x2), @@ -139,7 +144,7 @@ export class SelectZoom { if (this.options.enableY) { const y1 = Math.max(this.start.p.y, p.y); const y2 = Math.min(this.start.p.y, p.y); - if (y1 - y2 > 0) { + if (y1 - y2 > this.options.thresholdY) { const newDomain = [ this.chart.model.yScale.invert(y1), this.chart.model.yScale.invert(y2), From bed460fcf41cc7e8dd9e356b9cb385a3f903a536 Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 21 Apr 2024 01:58:30 +0200 Subject: [PATCH 2/7] Fix application of zoom onMouseUp event --- src/plugins_extra/selectZoom.ts | 44 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index c006ba1..2126d86 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -126,33 +126,29 @@ export class SelectZoom { return; const p = this.getPoint(ev); + const x1 = Math.min(this.start.p.x, p.x); + const x2 = Math.max(this.start.p.x, p.x); + const y1 = Math.max(this.start.p.y, p.y); + const y2 = Math.min(this.start.p.y, p.y); let changed = false; - if (this.options.enableX) { - const x1 = Math.min(this.start.p.x, p.x); - const x2 = Math.max(this.start.p.x, p.x); - if (x2 - x1 > this.options.thresholdX) { - const newDomain = [ - this.chart.model.xScale.invert(x1), - this.chart.model.xScale.invert(x2), - ]; - this.chart.model.xScale.domain(newDomain); - this.chart.options.xRange = null; - changed = true; - } + if (this.options.enableX && (x2 - x1 > 0) && ((x2 - x1 >= y1 - y2) || (x2 - x1 > this.options.thresholdX))) { + const newDomain = [ + this.chart.model.xScale.invert(x1), + this.chart.model.xScale.invert(x2), + ]; + this.chart.model.xScale.domain(newDomain); + this.chart.options.xRange = null; + changed = true; } - if (this.options.enableY) { - const y1 = Math.max(this.start.p.y, p.y); - const y2 = Math.min(this.start.p.y, p.y); - if (y1 - y2 > this.options.thresholdY) { - const newDomain = [ - this.chart.model.yScale.invert(y1), - this.chart.model.yScale.invert(y2), - ]; - this.chart.model.yScale.domain(newDomain); - this.chart.options.yRange = null; - changed = true; - } + if (this.options.enableY && (y1 - y2 > 0) && ((y1 - y2 > x2 - x1) || (y1 - y2 > this.options.thresholdY))) { + const newDomain = [ + this.chart.model.yScale.invert(y1), + this.chart.model.yScale.invert(y2), + ]; + this.chart.model.yScale.domain(newDomain); + this.chart.options.yRange = null; + changed = true; } if (changed) this.chart.model.requestRedraw(); From 784e3249ac974a935ea378c09ce2db0a1b008c2d Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 28 Apr 2024 22:56:15 +0200 Subject: [PATCH 3/7] Improve selection conditions --- src/plugins_extra/selectZoom.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index 2126d86..659456e 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -100,11 +100,15 @@ export class SelectZoom { const p = this.getPoint(ev); const x = Math.min(this.start.p.x, p.x); - const w = Math.abs(this.start.p.x - p.x); const y = Math.min(this.start.p.y, p.y); + const w = Math.abs(this.start.p.x - p.x); const h = Math.abs(this.start.p.y - p.y); + const minW = Math.min(h, this.options.thresholdX); + const minH = Math.min(w, this.options.thresholdY); + const selectX = w >= minW || !this.options.enableY; + const selectY = h >= minH || !this.options.enableX; - if (this.options.enableX && ((w >= h) || (w >= this.options.thresholdX))) { + if (this.options.enableX && selectX) { this.visual.x.baseVal.value = x; this.visual.width.baseVal.value = w; } else { @@ -112,7 +116,7 @@ export class SelectZoom { this.visual.setAttribute('width', '100%'); } - if (this.options.enableY && ((h > w) || (h >= this.options.thresholdY))) { + if (this.options.enableY && selectY) { this.visual.y.baseVal.value = y; this.visual.height.baseVal.value = h; } else { @@ -130,9 +134,15 @@ export class SelectZoom { const x2 = Math.max(this.start.p.x, p.x); const y1 = Math.max(this.start.p.y, p.y); const y2 = Math.min(this.start.p.y, p.y); + const w = Math.abs(x2 - x1); + const h = Math.abs(y2 - y1); + const minW = Math.min(h, this.options.thresholdX); + const minH = Math.min(w, this.options.thresholdY); + const selectX = w >= minW || !this.options.enableY; + const selectY = h >= minH || !this.options.enableX; let changed = false; - if (this.options.enableX && (x2 - x1 > 0) && ((x2 - x1 >= y1 - y2) || (x2 - x1 > this.options.thresholdX))) { + if (this.options.enableX && selectX && x2 != x1) { const newDomain = [ this.chart.model.xScale.invert(x1), this.chart.model.xScale.invert(x2), @@ -141,7 +151,7 @@ export class SelectZoom { this.chart.options.xRange = null; changed = true; } - if (this.options.enableY && (y1 - y2 > 0) && ((y1 - y2 > x2 - x1) || (y1 - y2 > this.options.thresholdY))) { + if (this.options.enableY && selectY && y2 != y1) { const newDomain = [ this.chart.model.yScale.invert(y1), this.chart.model.yScale.invert(y2), From ca7b774f227a93163122a506827b41b9105d2ba3 Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 28 Apr 2024 22:58:57 +0200 Subject: [PATCH 4/7] Add private properties for the select flags --- src/plugins_extra/selectZoom.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index 659456e..05af951 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -54,6 +54,8 @@ export class SelectZoom { } private start: {p: Point, id: number} | null = null; + private selectX: boolean = false; + private selectY: boolean = false; private reset() { if (this.start === null) @@ -105,10 +107,10 @@ export class SelectZoom { const h = Math.abs(this.start.p.y - p.y); const minW = Math.min(h, this.options.thresholdX); const minH = Math.min(w, this.options.thresholdY); - const selectX = w >= minW || !this.options.enableY; - const selectY = h >= minH || !this.options.enableX; + this.selectX = w >= minW || !this.options.enableY; + this.selectY = h >= minH || !this.options.enableX; - if (this.options.enableX && selectX) { + if (this.options.enableX && this.selectX) { this.visual.x.baseVal.value = x; this.visual.width.baseVal.value = w; } else { @@ -116,7 +118,7 @@ export class SelectZoom { this.visual.setAttribute('width', '100%'); } - if (this.options.enableY && selectY) { + if (this.options.enableY && this.selectY) { this.visual.y.baseVal.value = y; this.visual.height.baseVal.value = h; } else { @@ -134,15 +136,9 @@ export class SelectZoom { const x2 = Math.max(this.start.p.x, p.x); const y1 = Math.max(this.start.p.y, p.y); const y2 = Math.min(this.start.p.y, p.y); - const w = Math.abs(x2 - x1); - const h = Math.abs(y2 - y1); - const minW = Math.min(h, this.options.thresholdX); - const minH = Math.min(w, this.options.thresholdY); - const selectX = w >= minW || !this.options.enableY; - const selectY = h >= minH || !this.options.enableX; let changed = false; - if (this.options.enableX && selectX && x2 != x1) { + if (this.options.enableX && this.selectX && x2 != x1) { const newDomain = [ this.chart.model.xScale.invert(x1), this.chart.model.xScale.invert(x2), @@ -151,7 +147,7 @@ export class SelectZoom { this.chart.options.xRange = null; changed = true; } - if (this.options.enableY && selectY && y2 != y1) { + if (this.options.enableY && this.selectY && y2 != y1) { const newDomain = [ this.chart.model.yScale.invert(y1), this.chart.model.yScale.invert(y2), From 3e5b30e9a62de9824aef55768cdf2c4f3481191e Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 28 Apr 2024 23:02:46 +0200 Subject: [PATCH 5/7] Handle special case of equal width and height --- src/plugins_extra/selectZoom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index 05af951..9a9f34c 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -108,7 +108,7 @@ export class SelectZoom { const minW = Math.min(h, this.options.thresholdX); const minH = Math.min(w, this.options.thresholdY); this.selectX = w >= minW || !this.options.enableY; - this.selectY = h >= minH || !this.options.enableX; + this.selectY = h > minH || !this.options.enableX; if (this.options.enableX && this.selectX) { this.visual.x.baseVal.value = x; From 700df876c83a2d16d8384123c2a65f896b0f1afb Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 28 Apr 2024 23:03:29 +0200 Subject: [PATCH 6/7] Rename w and h to width and height --- src/plugins_extra/selectZoom.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins_extra/selectZoom.ts b/src/plugins_extra/selectZoom.ts index 9a9f34c..27c24e4 100644 --- a/src/plugins_extra/selectZoom.ts +++ b/src/plugins_extra/selectZoom.ts @@ -103,16 +103,16 @@ export class SelectZoom { const x = Math.min(this.start.p.x, p.x); const y = Math.min(this.start.p.y, p.y); - const w = Math.abs(this.start.p.x - p.x); - const h = Math.abs(this.start.p.y - p.y); - const minW = Math.min(h, this.options.thresholdX); - const minH = Math.min(w, this.options.thresholdY); - this.selectX = w >= minW || !this.options.enableY; - this.selectY = h > minH || !this.options.enableX; + const width = Math.abs(this.start.p.x - p.x); + const height = Math.abs(this.start.p.y - p.y); + const minWidth = Math.min(height, this.options.thresholdX); + const minHeight = Math.min(width, this.options.thresholdY); + this.selectX = width >= minWidth || !this.options.enableY; + this.selectY = height > minHeight || !this.options.enableX; if (this.options.enableX && this.selectX) { this.visual.x.baseVal.value = x; - this.visual.width.baseVal.value = w; + this.visual.width.baseVal.value = width; } else { this.visual.setAttribute('x', '0'); this.visual.setAttribute('width', '100%'); @@ -120,7 +120,7 @@ export class SelectZoom { if (this.options.enableY && this.selectY) { this.visual.y.baseVal.value = y; - this.visual.height.baseVal.value = h; + this.visual.height.baseVal.value = height; } else { this.visual.setAttribute('y', '0'); this.visual.setAttribute('height', '100%'); From f029408fc197a779e195745dc39accbe3ddacbb8 Mon Sep 17 00:00:00 2001 From: Janek Fleper Date: Sun, 28 Apr 2024 23:17:03 +0200 Subject: [PATCH 7/7] Add inputs for the select thresholds --- demo/plugins/select.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/demo/plugins/select.html b/demo/plugins/select.html index cadcef0..cf337c4 100644 --- a/demo/plugins/select.html +++ b/demo/plugins/select.html @@ -16,6 +16,12 @@

Select & Zoom with Mouse

+ + + + + + @@ -54,9 +60,11 @@

Select & Zoom with Mouse

const form = document.querySelector('form'); function syncSelectZoom() { - const { x, y } = form; + const { x, y, thresholdX, thresholdY } = form; chart.plugins.selectZoom.options.enableX = x.checked; chart.plugins.selectZoom.options.enableY = y.checked; + chart.plugins.selectZoom.options.thresholdX = thresholdX.value; + chart.plugins.selectZoom.options.thresholdY = thresholdY.value; } form.addEventListener('change', syncSelectZoom); syncSelectZoom();