Canvas: Enable ability to instantly select and drag an element (#52861)

Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
Drew Slobodnjak 2022-07-28 16:55:31 -07:00 committed by GitHub
parent 7c40257baf
commit e2044cde13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 15 deletions

View File

@ -71,7 +71,7 @@ export class ElementState implements LayerElement {
}
/** Use the configured options to update CSS style properties directly on the wrapper div **/
applyLayoutStylesToDiv() {
applyLayoutStylesToDiv(disablePointerEvents?: boolean) {
if (this.isRoot()) {
// Root supersedes layout engine and is always 100% width + height of panel
return;
@ -85,6 +85,7 @@ export class ElementState implements LayerElement {
const style: React.CSSProperties = {
cursor: editingEnabled ? 'grab' : 'auto',
pointerEvents: disablePointerEvents ? 'none' : 'auto',
position: 'absolute',
// Minimum element size is 10x10
minWidth: '10px',
@ -196,18 +197,28 @@ export class ElementState implements LayerElement {
if (!elementContainer) {
elementContainer = this.div && this.div.getBoundingClientRect();
}
let parentBorderWidth = 0;
if (!parentContainer) {
parentContainer = this.div && this.div.parentElement?.getBoundingClientRect();
parentBorderWidth = parseFloat(getComputedStyle(this.div?.parentElement!).borderWidth);
}
const relativeTop =
elementContainer && parentContainer ? Math.round(elementContainer.top - parentContainer.top) : 0;
elementContainer && parentContainer
? Math.round(elementContainer.top - parentContainer.top - parentBorderWidth)
: 0;
const relativeBottom =
elementContainer && parentContainer ? Math.round(parentContainer.bottom - elementContainer.bottom) : 0;
elementContainer && parentContainer
? Math.round(parentContainer.bottom - parentBorderWidth - elementContainer.bottom)
: 0;
const relativeLeft =
elementContainer && parentContainer ? Math.round(elementContainer.left - parentContainer.left) : 0;
elementContainer && parentContainer
? Math.round(elementContainer.left - parentContainer.left - parentBorderWidth)
: 0;
const relativeRight =
elementContainer && parentContainer ? Math.round(parentContainer.right - elementContainer.right) : 0;
elementContainer && parentContainer
? Math.round(parentContainer.right - parentBorderWidth - elementContainer.right)
: 0;
const placement = {} as Placement;

View File

@ -253,6 +253,22 @@ export class Scene {
return undefined;
};
setNonTargetPointerEvents = (target: HTMLElement | SVGElement, disablePointerEvents: boolean) => {
const stack = [...this.root.elements];
while (stack.length > 0) {
const currentElement = stack.shift();
if (currentElement && currentElement.div && currentElement.div !== target) {
currentElement.applyLayoutStylesToDiv(disablePointerEvents);
}
const nestedElements = currentElement instanceof FrameState ? currentElement.elements : [];
for (const nestedElement of nestedElements) {
stack.unshift(nestedElement);
}
}
};
setRef = (sceneContainer: HTMLDivElement) => {
this.div = sceneContainer;
};
@ -266,7 +282,6 @@ export class Scene {
private updateSelection = (selection: SelectionParams) => {
this.moveable!.target = selection.targets;
if (this.skipNextSelectionBroadcast) {
this.skipNextSelectionBroadcast = false;
return;
@ -332,6 +347,7 @@ export class Scene {
})
.on('dragStart', (event) => {
this.ignoreDataUpdate = true;
this.setNonTargetPointerEvents(event.target, true);
})
.on('dragGroupStart', (event) => {
this.ignoreDataUpdate = true;
@ -365,6 +381,7 @@ export class Scene {
this.moved.next(Date.now());
this.ignoreDataUpdate = false;
this.setNonTargetPointerEvents(event.target, false);
})
.on('resizeStart', (event) => {
const targetedElement = this.findElementByTarget(event.target);
@ -428,15 +445,15 @@ export class Scene {
targets = event.selected;
this.updateSelection({ targets });
// @TODO Figure out click-drag functionality without phantom mouseup issue
// https://github.com/daybrush/moveable/issues/481
// if (event.isDragStart) {
// event.inputEvent.preventDefault();
// setTimeout(() => {
// this.moveable!.dragStart(event.inputEvent);
// });
// }
if (event.isDragStart) {
if (this.isEditingEnabled && this.selecto?.getSelectedTargets().length) {
this.selecto.getSelectedTargets()[0].style.cursor = 'grabbing';
}
event.inputEvent.preventDefault();
setTimeout(() => {
this.moveable!.dragStart(event.inputEvent);
});
}
});
};