rename visualobserver
This commit is contained in:
parent
1475c41a85
commit
fee3a9f342
|
|
@ -1,8 +1,8 @@
|
||||||
import { FolkGeometry } from '../canvas/fc-geometry';
|
import { FolkGeometry } from '../canvas/fc-geometry';
|
||||||
import { Vertex } from './utils';
|
import { Vertex } from './utils';
|
||||||
import { VisualObserverEntry, VisualObserverManager } from './visual-observer';
|
import { ClientRectObserverEntry, ClientRectObserverManager } from './visual-observer';
|
||||||
|
|
||||||
const visualObserver = new VisualObserverManager();
|
const clientRectObserver = new ClientRectObserverManager();
|
||||||
|
|
||||||
const vertexRegex = /(?<x>-?([0-9]*[.])?[0-9]+),\s*(?<y>-?([0-9]*[.])?[0-9]+)/;
|
const vertexRegex = /(?<x>-?([0-9]*[.])?[0-9]+),\s*(?<y>-?([0-9]*[.])?[0-9]+)/;
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ export class AbstractArrow extends HTMLElement {
|
||||||
return this.#sourceElement;
|
return this.#sourceElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sourceCallback = (entry: VisualObserverEntry) => {
|
#sourceCallback = (entry: ClientRectObserverEntry) => {
|
||||||
this.#sourceRect = entry.contentRect;
|
this.#sourceRect = entry.contentRect;
|
||||||
this.#update();
|
this.#update();
|
||||||
};
|
};
|
||||||
|
|
@ -88,7 +88,7 @@ export class AbstractArrow extends HTMLElement {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#sourceIframeCallback = (entry: VisualObserverEntry) => {
|
#sourceIframeCallback = (entry: ClientRectObserverEntry) => {
|
||||||
this.#sourceIframeRect = entry.contentRect;
|
this.#sourceIframeRect = entry.contentRect;
|
||||||
this.#updateSourceIframeRect();
|
this.#updateSourceIframeRect();
|
||||||
};
|
};
|
||||||
|
|
@ -124,7 +124,7 @@ export class AbstractArrow extends HTMLElement {
|
||||||
return this.#targetElement;
|
return this.#targetElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
#targetCallback = (entry: VisualObserverEntry) => {
|
#targetCallback = (entry: ClientRectObserverEntry) => {
|
||||||
this.#targetRect = entry.contentRect;
|
this.#targetRect = entry.contentRect;
|
||||||
this.#update();
|
this.#update();
|
||||||
};
|
};
|
||||||
|
|
@ -162,7 +162,7 @@ export class AbstractArrow extends HTMLElement {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#targetIframeCallback = (entry: VisualObserverEntry) => {
|
#targetIframeCallback = (entry: ClientRectObserverEntry) => {
|
||||||
this.#targetIframeRect = entry.contentRect;
|
this.#targetIframeRect = entry.contentRect;
|
||||||
this.#updateTargetIframeRect();
|
this.#updateTargetIframeRect();
|
||||||
};
|
};
|
||||||
|
|
@ -214,13 +214,13 @@ export class AbstractArrow extends HTMLElement {
|
||||||
this.#sourceRect = this.#sourceElement.getBoundingClientRect();
|
this.#sourceRect = this.#sourceElement.getBoundingClientRect();
|
||||||
} else if (this.#sourceElement instanceof HTMLIFrameElement && this.#sourceIframeSelector) {
|
} else if (this.#sourceElement instanceof HTMLIFrameElement && this.#sourceIframeSelector) {
|
||||||
window.addEventListener('message', this.#sourcePostMessage);
|
window.addEventListener('message', this.#sourcePostMessage);
|
||||||
visualObserver.observe(this.#sourceElement, this.#sourceIframeCallback);
|
clientRectObserver.observe(this.#sourceElement, this.#sourceIframeCallback);
|
||||||
this.#sourceElement.contentWindow?.postMessage({
|
this.#sourceElement.contentWindow?.postMessage({
|
||||||
type: 'folk-observe-element',
|
type: 'folk-observe-element',
|
||||||
selector: this.#sourceIframeSelector,
|
selector: this.#sourceIframeSelector,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
visualObserver.observe(this.#sourceElement, this.#sourceCallback);
|
clientRectObserver.observe(this.#sourceElement, this.#sourceCallback);
|
||||||
this.#sourceRect = this.#sourceElement.getBoundingClientRect();
|
this.#sourceRect = this.#sourceElement.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,13 +234,13 @@ export class AbstractArrow extends HTMLElement {
|
||||||
this.#sourceElement.removeEventListener('move', this.#sourceHandler);
|
this.#sourceElement.removeEventListener('move', this.#sourceHandler);
|
||||||
} else if (this.#sourceElement instanceof HTMLIFrameElement && this.#sourceIframeSelector) {
|
} else if (this.#sourceElement instanceof HTMLIFrameElement && this.#sourceIframeSelector) {
|
||||||
window.removeEventListener('message', this.#sourcePostMessage);
|
window.removeEventListener('message', this.#sourcePostMessage);
|
||||||
visualObserver.unobserve(this.#sourceElement, this.#sourceIframeCallback);
|
clientRectObserver.unobserve(this.#sourceElement, this.#sourceIframeCallback);
|
||||||
this.#sourceElement.contentWindow?.postMessage({
|
this.#sourceElement.contentWindow?.postMessage({
|
||||||
type: 'folk-unobserve-element',
|
type: 'folk-unobserve-element',
|
||||||
selector: this.#sourceIframeSelector,
|
selector: this.#sourceIframeSelector,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
visualObserver.unobserve(this.#sourceElement, this.#sourceCallback);
|
clientRectObserver.unobserve(this.#sourceElement, this.#sourceCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,13 +264,13 @@ export class AbstractArrow extends HTMLElement {
|
||||||
this.#targetElement.addEventListener('move', this.#targetHandler);
|
this.#targetElement.addEventListener('move', this.#targetHandler);
|
||||||
} else if (this.#targetElement instanceof HTMLIFrameElement && this.#targetIframeSelector) {
|
} else if (this.#targetElement instanceof HTMLIFrameElement && this.#targetIframeSelector) {
|
||||||
window.addEventListener('message', this.#targetPostMessage);
|
window.addEventListener('message', this.#targetPostMessage);
|
||||||
visualObserver.observe(this.#targetElement, this.#targetIframeCallback);
|
clientRectObserver.observe(this.#targetElement, this.#targetIframeCallback);
|
||||||
this.#targetElement.contentWindow?.postMessage({
|
this.#targetElement.contentWindow?.postMessage({
|
||||||
type: 'folk-observe-element',
|
type: 'folk-observe-element',
|
||||||
selector: this.#targetIframeSelector,
|
selector: this.#targetIframeSelector,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
visualObserver.observe(this.#targetElement, this.#targetCallback);
|
clientRectObserver.observe(this.#targetElement, this.#targetCallback);
|
||||||
}
|
}
|
||||||
this.#targetRect = this.#targetElement.getBoundingClientRect();
|
this.#targetRect = this.#targetElement.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
|
@ -284,13 +284,13 @@ export class AbstractArrow extends HTMLElement {
|
||||||
this.#targetElement.removeEventListener('move', this.#targetHandler);
|
this.#targetElement.removeEventListener('move', this.#targetHandler);
|
||||||
} else if (this.#targetElement instanceof HTMLIFrameElement && this.#targetIframeSelector) {
|
} else if (this.#targetElement instanceof HTMLIFrameElement && this.#targetIframeSelector) {
|
||||||
window.removeEventListener('message', this.#targetPostMessage);
|
window.removeEventListener('message', this.#targetPostMessage);
|
||||||
visualObserver.unobserve(this.#targetElement, this.#targetIframeCallback);
|
clientRectObserver.unobserve(this.#targetElement, this.#targetIframeCallback);
|
||||||
this.#targetElement.contentWindow?.postMessage({
|
this.#targetElement.contentWindow?.postMessage({
|
||||||
type: 'folk-unobserve-element',
|
type: 'folk-unobserve-element',
|
||||||
selector: this.#targetIframeSelector,
|
selector: this.#targetIframeSelector,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
visualObserver.unobserve(this.#targetElement, this.#targetCallback);
|
clientRectObserver.unobserve(this.#targetElement, this.#targetCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { FolkGeometry } from '../canvas/fc-geometry';
|
import { FolkGeometry } from '../canvas/fc-geometry';
|
||||||
import { VisualObserverManager, VisualObserverEntry } from './visual-observer.ts';
|
import { ClientRectObserverManager, ClientRectObserverEntry } from './visual-observer.ts';
|
||||||
|
|
||||||
interface ObservedElementEntry {
|
interface ObservedElementEntry {
|
||||||
selector: string;
|
selector: string;
|
||||||
|
|
@ -51,7 +51,7 @@ if (window.parent !== window) {
|
||||||
const observedElements = new Map();
|
const observedElements = new Map();
|
||||||
const observedSelectors = new Map();
|
const observedSelectors = new Map();
|
||||||
|
|
||||||
function boundingBoxCallback(entry: VisualObserverEntry) {}
|
function boundingBoxCallback(entry: ClientRectObserverEntry) {}
|
||||||
|
|
||||||
function onGeometryChange(event) {
|
function onGeometryChange(event) {
|
||||||
window.parent.postMessage({
|
window.parent.postMessage({
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
export interface VisualObserverEntry {
|
export interface ClientRectObserverEntry {
|
||||||
target: Element;
|
target: Element;
|
||||||
contentRect: DOMRectReadOnly;
|
contentRect: DOMRectReadOnly;
|
||||||
isAppearing: boolean;
|
isAppearing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VisualObserverCallback {
|
export interface ClientRectObserverCallback {
|
||||||
(this: VisualObserver, entries: VisualObserverEntry[], observer: VisualObserver): void;
|
(this: ClientRectObserver, entries: ClientRectObserverEntry[], observer: ClientRectObserver): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VisualObserverElement {
|
interface ClientRectObserverElement {
|
||||||
io: IntersectionObserver | null;
|
io: IntersectionObserver | null;
|
||||||
threshold: number;
|
threshold: number;
|
||||||
isFirstUpdate: boolean;
|
isFirstUpdate: boolean;
|
||||||
|
|
@ -17,20 +17,20 @@ interface VisualObserverElement {
|
||||||
/**
|
/**
|
||||||
* Create an observer that notifies when an element is resized, moved, or added/removed from the DOM.
|
* Create an observer that notifies when an element is resized, moved, or added/removed from the DOM.
|
||||||
*/
|
*/
|
||||||
export class VisualObserver {
|
export class ClientRectObserver {
|
||||||
#root = document.documentElement;
|
#root = document.documentElement;
|
||||||
#rootRect = this.#root.getBoundingClientRect();
|
#rootRect = this.#root.getBoundingClientRect();
|
||||||
|
|
||||||
#entries: VisualObserverEntry[] = [];
|
#entries: ClientRectObserverEntry[] = [];
|
||||||
#rafId = 0;
|
#rafId = 0;
|
||||||
|
|
||||||
#callback: VisualObserverCallback;
|
#callback: ClientRectObserverCallback;
|
||||||
|
|
||||||
constructor(callback: VisualObserverCallback) {
|
constructor(callback: ClientRectObserverCallback) {
|
||||||
this.#callback = callback;
|
this.#callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elements = new Map<Element, VisualObserverElement>();
|
#elements = new Map<Element, ClientRectObserverElement>();
|
||||||
|
|
||||||
#resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
#resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
||||||
const rootEntry = entries.find((entry) => entry.target === this.#root);
|
const rootEntry = entries.find((entry) => entry.target === this.#root);
|
||||||
|
|
@ -49,7 +49,7 @@ export class VisualObserver {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#appendEntry(entry: VisualObserverEntry) {
|
#appendEntry(entry: ClientRectObserverEntry) {
|
||||||
// deduplicate the same target
|
// deduplicate the same target
|
||||||
this.#entries.push(entry);
|
this.#entries.push(entry);
|
||||||
|
|
||||||
|
|
@ -66,9 +66,7 @@ export class VisualObserver {
|
||||||
};
|
};
|
||||||
|
|
||||||
// We should be guaranteed that each `IntersectionObserver` only observes one element.
|
// We should be guaranteed that each `IntersectionObserver` only observes one element.
|
||||||
#onIntersection = ([
|
#onIntersection = ([{ target, intersectionRatio, boundingClientRect }]: IntersectionObserverEntry[]) => {
|
||||||
{ target, intersectionRatio, boundingClientRect },
|
|
||||||
]: IntersectionObserverEntry[]) => {
|
|
||||||
const el = this.#elements.get(target);
|
const el = this.#elements.get(target);
|
||||||
|
|
||||||
if (el === undefined) return;
|
if (el === undefined) return;
|
||||||
|
|
@ -100,7 +98,7 @@ export class VisualObserver {
|
||||||
#refreshElement(
|
#refreshElement(
|
||||||
target: Element,
|
target: Element,
|
||||||
contentRect: DOMRectReadOnly = target.getBoundingClientRect()
|
contentRect: DOMRectReadOnly = target.getBoundingClientRect()
|
||||||
): VisualObserverEntry {
|
): ClientRectObserverEntry {
|
||||||
// Assume el exists
|
// Assume el exists
|
||||||
const el = this.#elements.get(target)!;
|
const el = this.#elements.get(target)!;
|
||||||
|
|
||||||
|
|
@ -176,7 +174,7 @@ export class VisualObserver {
|
||||||
this.#resizeObserver.observe(target);
|
this.#resizeObserver.observe(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
takeRecords(): VisualObserverEntry[] {
|
takeRecords(): ClientRectObserverEntry[] {
|
||||||
if (this.#rafId === 0) return [];
|
if (this.#rafId === 0) return [];
|
||||||
|
|
||||||
const entries = this.#entries;
|
const entries = this.#entries;
|
||||||
|
|
@ -203,12 +201,12 @@ export class VisualObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VisualObserverEntryCallback = (entry: VisualObserverEntry) => void;
|
export type ClientRectObserverEntryCallback = (entry: ClientRectObserverEntry) => void;
|
||||||
|
|
||||||
export class VisualObserverManager {
|
export class ClientRectObserverManager {
|
||||||
#elementMap = new WeakMap<Element, Set<VisualObserverEntryCallback>>();
|
#elementMap = new WeakMap<Element, Set<ClientRectObserverEntryCallback>>();
|
||||||
|
|
||||||
#vo = new VisualObserver((entries) => {
|
#vo = new ClientRectObserver((entries) => {
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
const callbacks = this.#elementMap.get(entry.target);
|
const callbacks = this.#elementMap.get(entry.target);
|
||||||
|
|
||||||
|
|
@ -218,7 +216,7 @@ export class VisualObserverManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
observe(target: Element, callback: VisualObserverEntryCallback): void {
|
observe(target: Element, callback: ClientRectObserverEntryCallback): void {
|
||||||
let callbacks = this.#elementMap.get(target);
|
let callbacks = this.#elementMap.get(target);
|
||||||
|
|
||||||
if (callbacks === undefined) {
|
if (callbacks === undefined) {
|
||||||
|
|
@ -231,7 +229,7 @@ export class VisualObserverManager {
|
||||||
callbacks.add(callback);
|
callbacks.add(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
unobserve(target: Element, callback: VisualObserverEntryCallback): void {
|
unobserve(target: Element, callback: ClientRectObserverEntryCallback): void {
|
||||||
let callbacks = this.#elementMap.get(target);
|
let callbacks = this.#elementMap.get(target);
|
||||||
|
|
||||||
if (callbacks === undefined) return;
|
if (callbacks === undefined) return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue