mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Lexical: Made image resize handles functional
This commit is contained in:
parent
ba871ec46a
commit
e959c468f6
@ -80,7 +80,6 @@ export class ImageNode extends DecoratorNode<EditorDecoratorAdapter> {
|
||||
setWidth(width: number): void {
|
||||
const self = this.getWritable();
|
||||
self.__width = width;
|
||||
console.log('widrg', width)
|
||||
}
|
||||
|
||||
getWidth(): number {
|
||||
|
@ -7,48 +7,65 @@ import {ImageNode} from "../../nodes/image";
|
||||
|
||||
export class ImageDecorator extends EditorDecorator {
|
||||
protected dom: HTMLElement|null = null;
|
||||
protected dragLastMouseUp: number = 0;
|
||||
|
||||
buildDOM(context: EditorUiContext) {
|
||||
const handleClasses = ['nw', 'ne', 'se', 'sw'];
|
||||
const handleEls = handleClasses.map(c => {
|
||||
return el('div', {class: `editor-image-decorator-handle ${c}`});
|
||||
});
|
||||
|
||||
let handleElems: HTMLElement[] = [];
|
||||
const decorateEl = el('div', {
|
||||
class: 'editor-image-decorator',
|
||||
}, handleEls);
|
||||
}, []);
|
||||
let selected = false;
|
||||
|
||||
const windowClick = (event: MouseEvent) => {
|
||||
if (!decorateEl.contains(event.target as Node)) {
|
||||
if (!decorateEl.contains(event.target as Node) && (Date.now() - this.dragLastMouseUp > 100)) {
|
||||
unselect();
|
||||
}
|
||||
};
|
||||
|
||||
const mouseDown = (event: MouseEvent) => {
|
||||
const handle = (event.target as HTMLElement).closest('.editor-image-decorator-handle') as HTMLElement|null;
|
||||
if (handle) {
|
||||
// handlingResize = true;
|
||||
this.startHandlingResize(handle, event, context);
|
||||
}
|
||||
};
|
||||
|
||||
const select = () => {
|
||||
if (selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
selected = true;
|
||||
decorateEl.classList.add('selected');
|
||||
window.addEventListener('click', windowClick);
|
||||
};
|
||||
|
||||
const unselect = () => {
|
||||
decorateEl.classList.remove('selected');
|
||||
window.removeEventListener('click', windowClick);
|
||||
};
|
||||
const handleClasses = ['nw', 'ne', 'se', 'sw'];
|
||||
handleElems = handleClasses.map(c => {
|
||||
return el('div', {class: `editor-image-decorator-handle ${c}`});
|
||||
});
|
||||
decorateEl.append(...handleElems);
|
||||
decorateEl.addEventListener('mousedown', mouseDown);
|
||||
|
||||
decorateEl.addEventListener('click', (event) => {
|
||||
context.editor.update(() => {
|
||||
const nodeSelection = $createNodeSelection();
|
||||
nodeSelection.add(this.getNode().getKey());
|
||||
$setSelection(nodeSelection);
|
||||
});
|
||||
};
|
||||
|
||||
select();
|
||||
});
|
||||
|
||||
decorateEl.addEventListener('mousedown', (event: MouseEvent) => {
|
||||
const handle = (event.target as Element).closest('.editor-image-decorator-handle');
|
||||
if (handle) {
|
||||
this.startHandlingResize(handle, event, context);
|
||||
const unselect = () => {
|
||||
selected = false;
|
||||
// handlingResize = false;
|
||||
decorateEl.classList.remove('selected');
|
||||
window.removeEventListener('click', windowClick);
|
||||
decorateEl.removeEventListener('mousedown', mouseDown);
|
||||
for (const el of handleElems) {
|
||||
el.remove();
|
||||
}
|
||||
};
|
||||
|
||||
decorateEl.addEventListener('click', (event) => {
|
||||
select();
|
||||
});
|
||||
|
||||
return decorateEl;
|
||||
@ -63,26 +80,56 @@ export class ImageDecorator extends EditorDecorator {
|
||||
return this.dom;
|
||||
}
|
||||
|
||||
startHandlingResize(element: Node, event: MouseEvent, context: EditorUiContext) {
|
||||
startHandlingResize(element: HTMLElement, event: MouseEvent, context: EditorUiContext) {
|
||||
const startingX = event.screenX;
|
||||
const startingY = event.screenY;
|
||||
const node = this.getNode() as ImageNode;
|
||||
let startingWidth = element.clientWidth;
|
||||
let startingHeight = element.clientHeight;
|
||||
let startingRatio = startingWidth / startingHeight;
|
||||
let hasHeight = false;
|
||||
context.editor.getEditorState().read(() => {
|
||||
startingWidth = node.getWidth() || startingWidth;
|
||||
startingHeight = node.getHeight() || startingHeight;
|
||||
if (node.getHeight()) {
|
||||
hasHeight = true;
|
||||
}
|
||||
startingRatio = startingWidth / startingHeight;
|
||||
});
|
||||
|
||||
const flipXChange = element.classList.contains('nw') || element.classList.contains('sw');
|
||||
const flipYChange = element.classList.contains('nw') || element.classList.contains('ne');
|
||||
|
||||
const mouseMoveListener = (event: MouseEvent) => {
|
||||
const xChange = event.screenX - startingX;
|
||||
const yChange = event.screenY - startingY;
|
||||
console.log({ xChange, yChange });
|
||||
let xChange = event.screenX - startingX;
|
||||
if (flipXChange) {
|
||||
xChange = 0 - xChange;
|
||||
}
|
||||
let yChange = event.screenY - startingY;
|
||||
if (flipYChange) {
|
||||
yChange = 0 - yChange;
|
||||
}
|
||||
const balancedChange = Math.sqrt(Math.pow(xChange, 2) + Math.pow(yChange, 2));
|
||||
const increase = xChange + yChange > 0;
|
||||
const directedChange = increase ? balancedChange : 0-balancedChange;
|
||||
const newWidth = Math.max(5, Math.round(startingWidth + directedChange));
|
||||
let newHeight = 0;
|
||||
if (hasHeight) {
|
||||
newHeight = newWidth * startingRatio;
|
||||
}
|
||||
|
||||
context.editor.update(() => {
|
||||
const node = this.getNode() as ImageNode;
|
||||
node.setWidth(node.getWidth() + xChange);
|
||||
node.setHeight(node.getHeight() + yChange);
|
||||
node.setWidth(newWidth);
|
||||
node.setHeight(newHeight);
|
||||
});
|
||||
};
|
||||
|
||||
const mouseUpListener = (event: MouseEvent) => {
|
||||
window.removeEventListener('mousemove', mouseMoveListener);
|
||||
window.removeEventListener('mouseup', mouseUpListener);
|
||||
}
|
||||
this.dragLastMouseUp = Date.now();
|
||||
};
|
||||
|
||||
window.addEventListener('mousemove', mouseMoveListener);
|
||||
window.addEventListener('mouseup', mouseUpListener);
|
||||
|
@ -85,20 +85,23 @@
|
||||
display: inline-flex;
|
||||
}
|
||||
.editor-image-decorator {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
border: 1px solid var(--editor-color-primary);
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
&.selected {
|
||||
border: 1px dashed var(--editor-color-primary);
|
||||
}
|
||||
}
|
||||
.editor-image-decorator-handle {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: var(--editor-color-primary);
|
||||
border: 2px solid var(--editor-color-primary);
|
||||
background-color: #FFF;
|
||||
user-select: none;
|
||||
&.nw {
|
||||
inset-inline-start: -5px;
|
||||
|
Loading…
Reference in New Issue
Block a user