From 54f949a97239f080a6543d9e6128b64fa9ee2c95 Mon Sep 17 00:00:00 2001 From: Jon Bake Date: Sun, 28 Feb 2021 11:08:14 -0600 Subject: [PATCH] :bug: Fixes #1364 - Incorrect mouse selection when zoomed in or out (#1498) Prior to this change, the mouse selection box had a fixed position on the page. Nodes have absolute position within NodeView. This inconsistency in positioning caused issues when calculating if a node was positioned within the mouse selection. This solution makes both nodes and mouse selection have consistent positioning, along with correctly calculating the mouse click position within NodeView when making a selection. --- .../src/components/mixins/mouseSelect.ts | 47 ++++++++++++------- packages/editor-ui/src/views/NodeView.vue | 1 + 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/editor-ui/src/components/mixins/mouseSelect.ts b/packages/editor-ui/src/components/mixins/mouseSelect.ts index 0b280297f0..ad7fae8f07 100644 --- a/packages/editor-ui/src/components/mixins/mouseSelect.ts +++ b/packages/editor-ui/src/components/mixins/mouseSelect.ts @@ -23,14 +23,15 @@ export const mouseSelect = mixins( this.selectBox.id = 'select-box'; this.selectBox.style.margin = '0px auto'; this.selectBox.style.border = '2px dotted #FF0000'; - this.selectBox.style.position = 'fixed'; + // Positioned absolutely within #node-view. This is consistent with how nodes are positioned. + this.selectBox.style.position = 'absolute'; this.selectBox.style.zIndex = '100'; this.selectBox.style.visibility = 'hidden'; this.selectBox.addEventListener('mouseup', this.mouseUpMouseSelect); - // document.body.appendChild(this.selectBox); - this.$el.appendChild(this.selectBox); + const nodeViewEl = this.$el.querySelector('#node-view') as HTMLDivElement; + nodeViewEl.appendChild(this.selectBox); }, isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean { if (this.isTouchDevice === true) { @@ -41,14 +42,28 @@ export const mouseSelect = mixins( } return e.ctrlKey; }, + /** + * Gets mouse position within the node view. Both node view offset and scale (zoom) are considered when + * calculating position. + * + * @param event - mouse event within node view + */ + getMousePositionWithinNodeView (event: MouseEvent) { + // @ts-ignore + const nodeViewScale = this.nodeViewScale; + const offsetPosition = this.$store.getters.getNodeViewOffsetPosition; + return { + x: (event.pageX - offsetPosition[0]) / nodeViewScale, + y: (event.pageY - offsetPosition[1]) / nodeViewScale, + }; + }, showSelectBox (event: MouseEvent) { - // @ts-ignore - this.selectBox.x = event.pageX; - // @ts-ignore - this.selectBox.y = event.pageY; + this.selectBox = Object.assign(this.selectBox, this.getMousePositionWithinNodeView(event)); - this.selectBox.style.left = event.pageX + 'px'; - this.selectBox.style.top = event.pageY + 'px'; + // @ts-ignore + this.selectBox.style.left = this.selectBox.x + 'px'; + // @ts-ignore + this.selectBox.style.top = this.selectBox.y + 'px'; this.selectBox.style.visibility = 'visible'; this.selectActive = true; @@ -75,25 +90,21 @@ export const mouseSelect = mixins( this.selectActive = false; }, getSelectionBox (event: MouseEvent) { + const {x, y} = this.getMousePositionWithinNodeView(event); return { // @ts-ignore - x: Math.min(event.pageX, this.selectBox.x), + x: Math.min(x, this.selectBox.x), // @ts-ignore - y: Math.min(event.pageY, this.selectBox.y), + y: Math.min(y, this.selectBox.y), // @ts-ignore - width: Math.abs(event.pageX - this.selectBox.x), + width: Math.abs(x - this.selectBox.x), // @ts-ignore - height: Math.abs(event.pageY - this.selectBox.y), + height: Math.abs(y - this.selectBox.y), }; }, getNodesInSelection (event: MouseEvent): INodeUi[] { const returnNodes: INodeUi[] = []; const selectionBox = this.getSelectionBox(event); - const offsetPosition = this.$store.getters.getNodeViewOffsetPosition; - - // Consider the offset of the workflow when it got moved - selectionBox.x -= offsetPosition[0]; - selectionBox.y -= offsetPosition[1]; // Go through all nodes and check if they are selected this.$store.getters.allNodes.forEach((node: INodeUi) => { diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 173f0bbf71..65852033ef 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -2139,6 +2139,7 @@ export default mixins( position: relative; width: 100%; height: 100%; + transform-origin: 0 0; } .node-view-background {