From 129a33a94ff81ce8cac16dcc6e833def0b3936c1 Mon Sep 17 00:00:00 2001 From: Mario Buikhuizen Date: Mon, 13 Feb 2023 16:41:27 +0100 Subject: [PATCH] fix: panning in a by CSS rotated plot doesn't work correctly In Firefox and Safari, panning doesn't work correctly when a plots parent is rotated by CSS. --- js/src/PanZoom.ts | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/js/src/PanZoom.ts b/js/src/PanZoom.ts index 205ab5f6a..9ae38d77f 100644 --- a/js/src/PanZoom.ts +++ b/js/src/PanZoom.ts @@ -21,6 +21,8 @@ import * as _ from 'underscore'; const nop = () => {}; +const IS_CHROMIUM = navigator.userAgent.includes(' Chrome/'); + export class PanZoom extends interaction.Interaction { render() { super.render(); @@ -99,8 +101,43 @@ export class PanZoom extends interaction.Interaction { }); } + hasRotatedParent(element) { + const parent = element.parentNode; + /* Base case: the element has no parent or the parent is the element */ + if (!parent || parent.tagName === 'HTML') { + return false; + } + + /* Check if the parent is rotated */ + const computedStyle = window.getComputedStyle(parent); + const transform = computedStyle.getPropertyValue('transform'); + + if (transform !== 'none' && !transform.startsWith('matrix(1, 0, 0, 1')) { + return true; + } + + /* Recursively check the parent's parent */ + return this.hasRotatedParent(parent); + } + + mousePos() { + if (this.use_css_rotation_workaround) { + const mouseEvent = window.event as MouseEvent; + + /* the mouse position is only correct within this.el */ + if (mouseEvent.target === this.el) { + this.last_mouse_pos = [mouseEvent.offsetX, mouseEvent.offsetY]; + } + return this.last_mouse_pos; + } else { + return d3.mouse(this.el); + } + } + mousedown() { - this._mousedown(d3.mouse(this.el)); + this.use_css_rotation_workaround = + !IS_CHROMIUM && this.hasRotatedParent(this.el); + this._mousedown(this.mousePos()); } _mousedown(mouse_pos) { @@ -125,7 +162,7 @@ export class PanZoom extends interaction.Interaction { } mousemove() { - this._mousemove(d3.mouse(this.el)); + this._mousemove(this.mousePos()); } _mousemove(mouse_pos) { @@ -177,7 +214,7 @@ export class PanZoom extends interaction.Interaction { const event = d3GetEvent(); event.preventDefault(); const delta = event.deltaY * -1; - const mouse_pos = d3.mouse(this.el); + const mouse_pos = this.mousePos(); this._zoom(mouse_pos, delta); } } @@ -224,4 +261,6 @@ export class PanZoom extends interaction.Interaction { scale_promises: any; previous_pos: [number, number]; domains_in_order: { x: any[]; y: any[] }; + last_mouse_pos = null; + use_css_rotation_workaround: boolean; }