Use ResizeObserver to resize overlay if necessary

This commit is contained in:
Henrik Giesel 2021-07-21 17:37:58 +02:00 committed by Damien Elmes
parent 30e0894ad9
commit d22aa72964
2 changed files with 66 additions and 17 deletions

View file

@ -6,7 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import ImageHandleFloat from "./ImageHandleFloat.svelte"; import ImageHandleFloat from "./ImageHandleFloat.svelte";
import ImageHandleSizeSelect from "./ImageHandleSizeSelect.svelte"; import ImageHandleSizeSelect from "./ImageHandleSizeSelect.svelte";
import { getContext } from "svelte"; import { onDestroy, getContext } from "svelte";
import { nightModeKey } from "components/context-keys"; import { nightModeKey } from "components/context-keys";
export let image: HTMLImageElement | null = null; export let image: HTMLImageElement | null = null;
@ -37,6 +37,22 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
updateSizes(); updateSizes();
} }
const observer = new ResizeObserver(() => {
if (image) {
updateSizes();
}
});
function startObserving() {
observer.observe(container);
}
function stopObserving() {
observer.unobserve(container);
}
startObserving();
function updateSizes() { function updateSizes() {
const imageRect = image!.getBoundingClientRect(); const imageRect = image!.getBoundingClientRect();
const containerRect = container.getBoundingClientRect(); const containerRect = container.getBoundingClientRect();
@ -57,11 +73,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
return; return;
} }
stopObserving();
(event.target as Element).setPointerCapture(event.pointerId); (event.target as Element).setPointerCapture(event.pointerId);
} }
function resize(event: PointerEvent): void { function resize(event: PointerEvent): void {
if (!(event.target as Element).hasPointerCapture(event.pointerId)) { const element = event.target! as Element;
if (!element.hasPointerCapture(event.pointerId)) {
return; return;
} }
@ -92,6 +111,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
const nightMode = getContext(nightModeKey); const nightMode = getContext(nightModeKey);
onDestroy(() => observer.disconnect());
</script> </script>
{#if image && imageRule} {#if image && imageRule}
@ -99,7 +120,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
style="--top: {top}px; --left: {left}px; --width: {width}px; --height: {height}px;" style="--top: {top}px; --left: {left}px; --width: {width}px; --height: {height}px;"
class="image-handle-selection" class="image-handle-selection"
> >
<div class="image-handle-bg" on:dblclick={onDblclick} /> <div
class="image-handle-bg"
on:mousedown|preventDefault
on:dblclick={onDblclick}
/>
<div class="image-handle-buttons" class:is-rtl={isRtl}> <div class="image-handle-buttons" class:is-rtl={isRtl}>
<ImageHandleFloat {isRtl} bind:float={image.style.float} /> <ImageHandleFloat {isRtl} bind:float={image.style.float} />
</div> </div>
@ -119,20 +144,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{width}&times;{height} (Original: {naturalWidth}&times;{naturalHeight}) {width}&times;{height} (Original: {naturalWidth}&times;{naturalHeight})
</div> </div>
{/if} {/if}
<div class:nightMode class="image-handle-control image-handle-control-nw" /> <div
<div class:nightMode class="image-handle-control image-handle-control-ne" /> class:nightMode
class="image-handle-control image-handle-control-nw"
on:mousedown|preventDefault
/>
<div
class:nightMode
class="image-handle-control image-handle-control-ne"
on:mousedown|preventDefault
/>
<div <div
class:nightMode class:nightMode
class:active class:active
class="image-handle-control image-handle-control-sw" class="image-handle-control image-handle-control-sw"
on:mousedown|preventDefault
on:pointerdown={setPointerCapture} on:pointerdown={setPointerCapture}
on:pointerup={startObserving}
on:pointermove={resize} on:pointermove={resize}
/> />
<div <div
class:nightMode class:nightMode
class:active class:active
class="image-handle-control image-handle-control-se" class="image-handle-control image-handle-control-se"
on:mousedown|preventDefault
on:pointerdown={setPointerCapture} on:pointerdown={setPointerCapture}
on:pointerup={startObserving}
on:pointermove={resize} on:pointermove={resize}
/> />
</div> </div>

View file

@ -58,6 +58,9 @@ export class EditingArea extends HTMLDivElement {
}) as Codable; }) as Codable;
this.appendChild(this.codable); this.appendChild(this.codable);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onKey = this.onKey.bind(this);
this.onPaste = this.onPaste.bind(this); this.onPaste = this.onPaste.bind(this);
this.showImageHandle = this.showImageHandle.bind(this); this.showImageHandle = this.showImageHandle.bind(this);
} }
@ -79,17 +82,11 @@ export class EditingArea extends HTMLDivElement {
} }
connectedCallback(): void { connectedCallback(): void {
this.addEventListener("keydown", (event) => { this.addEventListener("keydown", this.onKey);
this.resetImageHandle();
onKey(event);
});
this.addEventListener("keyup", onKeyUp); this.addEventListener("keyup", onKeyUp);
this.addEventListener("input", onInput); this.addEventListener("input", onInput);
this.addEventListener("focusin", onFocus); this.addEventListener("focusin", this.onFocus);
this.addEventListener("focusout", (event) => { this.addEventListener("focusout", this.onBlur);
this.resetImageHandle();
onBlur(event);
});
this.addEventListener("paste", this.onPaste); this.addEventListener("paste", this.onPaste);
this.addEventListener("copy", onCutOrCopy); this.addEventListener("copy", onCutOrCopy);
this.addEventListener("oncut", onCutOrCopy); this.addEventListener("oncut", onCutOrCopy);
@ -98,11 +95,11 @@ export class EditingArea extends HTMLDivElement {
} }
disconnectedCallback(): void { disconnectedCallback(): void {
this.removeEventListener("keydown", onKey); this.removeEventListener("keydown", this.onKey);
this.removeEventListener("keyup", onKeyUp); this.removeEventListener("keyup", onKeyUp);
this.removeEventListener("input", onInput); this.removeEventListener("input", onInput);
this.removeEventListener("focusin", onFocus); this.removeEventListener("focusin", this.onFocus);
this.removeEventListener("focusout", onBlur); this.removeEventListener("focusout", this.onBlur);
this.removeEventListener("paste", this.onPaste); this.removeEventListener("paste", this.onPaste);
this.removeEventListener("copy", onCutOrCopy); this.removeEventListener("copy", onCutOrCopy);
this.removeEventListener("oncut", onCutOrCopy); this.removeEventListener("oncut", onCutOrCopy);
@ -164,11 +161,26 @@ export class EditingArea extends HTMLDivElement {
this.activeInput.surroundSelection(before, after); this.activeInput.surroundSelection(before, after);
} }
onFocus(event: FocusEvent): void {
onFocus(event);
}
onBlur(event: FocusEvent): void {
this.resetImageHandle();
onBlur(event);
}
onEnter(event: KeyboardEvent): void { onEnter(event: KeyboardEvent): void {
this.activeInput.onEnter(event); this.activeInput.onEnter(event);
} }
onKey(event: KeyboardEvent): void {
this.resetImageHandle();
onKey(event);
}
onPaste(event: ClipboardEvent): void { onPaste(event: ClipboardEvent): void {
this.resetImageHandle();
this.activeInput.onPaste(event); this.activeInput.onPaste(event);
} }