🐛 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.
This commit is contained in:
Jon Bake 2021-02-28 11:08:14 -06:00 committed by GitHub
parent 725b3eb408
commit 54f949a972
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 18 deletions

View file

@ -23,14 +23,15 @@ export const mouseSelect = mixins(
this.selectBox.id = 'select-box'; this.selectBox.id = 'select-box';
this.selectBox.style.margin = '0px auto'; this.selectBox.style.margin = '0px auto';
this.selectBox.style.border = '2px dotted #FF0000'; 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.zIndex = '100';
this.selectBox.style.visibility = 'hidden'; this.selectBox.style.visibility = 'hidden';
this.selectBox.addEventListener('mouseup', this.mouseUpMouseSelect); this.selectBox.addEventListener('mouseup', this.mouseUpMouseSelect);
// document.body.appendChild(this.selectBox); const nodeViewEl = this.$el.querySelector('#node-view') as HTMLDivElement;
this.$el.appendChild(this.selectBox); nodeViewEl.appendChild(this.selectBox);
}, },
isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean { isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean {
if (this.isTouchDevice === true) { if (this.isTouchDevice === true) {
@ -41,14 +42,28 @@ export const mouseSelect = mixins(
} }
return e.ctrlKey; 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) { showSelectBox (event: MouseEvent) {
// @ts-ignore this.selectBox = Object.assign(this.selectBox, this.getMousePositionWithinNodeView(event));
this.selectBox.x = event.pageX;
// @ts-ignore
this.selectBox.y = event.pageY;
this.selectBox.style.left = event.pageX + 'px'; // @ts-ignore
this.selectBox.style.top = event.pageY + 'px'; this.selectBox.style.left = this.selectBox.x + 'px';
// @ts-ignore
this.selectBox.style.top = this.selectBox.y + 'px';
this.selectBox.style.visibility = 'visible'; this.selectBox.style.visibility = 'visible';
this.selectActive = true; this.selectActive = true;
@ -75,25 +90,21 @@ export const mouseSelect = mixins(
this.selectActive = false; this.selectActive = false;
}, },
getSelectionBox (event: MouseEvent) { getSelectionBox (event: MouseEvent) {
const {x, y} = this.getMousePositionWithinNodeView(event);
return { return {
// @ts-ignore // @ts-ignore
x: Math.min(event.pageX, this.selectBox.x), x: Math.min(x, this.selectBox.x),
// @ts-ignore // @ts-ignore
y: Math.min(event.pageY, this.selectBox.y), y: Math.min(y, this.selectBox.y),
// @ts-ignore // @ts-ignore
width: Math.abs(event.pageX - this.selectBox.x), width: Math.abs(x - this.selectBox.x),
// @ts-ignore // @ts-ignore
height: Math.abs(event.pageY - this.selectBox.y), height: Math.abs(y - this.selectBox.y),
}; };
}, },
getNodesInSelection (event: MouseEvent): INodeUi[] { getNodesInSelection (event: MouseEvent): INodeUi[] {
const returnNodes: INodeUi[] = []; const returnNodes: INodeUi[] = [];
const selectionBox = this.getSelectionBox(event); 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 // Go through all nodes and check if they are selected
this.$store.getters.allNodes.forEach((node: INodeUi) => { this.$store.getters.allNodes.forEach((node: INodeUi) => {

View file

@ -2139,6 +2139,7 @@ export default mixins(
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
transform-origin: 0 0;
} }
.node-view-background { .node-view-background {