Skip to content

Commit

Permalink
Fix node bound displacement (#24)
Browse files Browse the repository at this point in the history
* Fix node bound displacement

* Finalized fix by replacing rect observer with polling and fixing incorrect mouseHandler validity

* Carry over fixes

* Fix disconnect removeEventListener
  • Loading branch information
Manfred Cheung authored Jan 19, 2021
1 parent c15d9c3 commit 7e4465a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 19 deletions.
23 changes: 7 additions & 16 deletions src/UX/mouse/MouseHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,29 +178,19 @@ export class MouseHandler extends EventEmitter.mixin(UXModule) {

private update(state: MouseState): void {
const events: EventEntry[] = [];
if (state.valid !== this.state.valid) {
this.state.valid = state.valid;
vec2.copy(this.state.clientCoords, state.clientCoords);
vec2.copy(this.state.canvasCoords, state.canvasCoords);
}
vec2.copy(this.state.deltaCoords, state.deltaCoords);
vec2.copy(this.state.clientCoords, state.clientCoords);
vec2.copy(this.state.canvasCoords, state.canvasCoords);
vec2.copy(this.state.glCoords, state.glCoords);

if (this.state.deltaCoords[0] !== 0 || this.state.deltaCoords[1] !== 0) {
if (this.state.valid) {
if (state.deltaCoords[0] !== 0 || state.deltaCoords[1] !== 0) {
if (state.valid) {
events.push({
event: kEvents.move,
args: [this.state.deltaCoords, this.state.canvasCoords],
args: [state.deltaCoords, state.canvasCoords],
});
}
}

const buttonKeys = Object.keys(state.buttons);
for (let i = 0, n = buttonKeys.length; i < n; ++i) {
const key = buttonKeys[i];
const pressed = this.state.valid && state.buttons[key];
const pressed = state.valid && state.buttons[key];
if (this.state.buttons[key] !== pressed) {
this.state.buttons[key] = pressed;
events.push({
Expand All @@ -209,7 +199,7 @@ export class MouseHandler extends EventEmitter.mixin(UXModule) {
});
}
}

this.setMouseState(state);
this.emitEvents(events);
}

Expand All @@ -223,6 +213,7 @@ export class MouseHandler extends EventEmitter.mixin(UXModule) {
this.state.valid = state.valid;
vec2.copy(this.state.clientCoords, state.clientCoords);
vec2.copy(this.state.canvasCoords, state.canvasCoords);
vec2.copy(this.state.glCoords, state.glCoords);
vec2.copy(this.state.deltaCoords, state.deltaCoords);
this.state.wheel = state.wheel;
Object.assign(this.state.buttons, state.buttons);
Expand Down Expand Up @@ -271,7 +262,7 @@ export class MouseHandler extends EventEmitter.mixin(UXModule) {

this.newState.valid = Boolean(
canvas[0] >= rect.left && canvas[0] <= rect.right &&
canvas[1] >= rect.top && canvas[1] <= rect.bottom
canvas[1] >= 0 && canvas[1] <= rect.height
);

this.newState.buttons.primary = Boolean(e.buttons & 1);
Expand Down
54 changes: 54 additions & 0 deletions src/renderer/RectObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
export type RectObserverCallback = (rect: DOMRectReadOnly) => void;

const POLLING_RATE = 400; // ms

export default class RectObserver {
public elementTarget: HTMLElement;
public callback: RectObserverCallback;
public rect: DOMRectReadOnly;
private poll: ReturnType<typeof setInterval>;

constructor(callback: RectObserverCallback) {
this.callback = callback;
}

public observe(element: HTMLElement): void {
this.elementTarget = element;

this.elementTarget.addEventListener("mouseenter", this.handleMouseEnter.bind(this), false);
this.elementTarget.addEventListener("mouseleave", this.handleMouseLeave.bind(this), false);

this.rect = this.elementTarget.getBoundingClientRect();
}

public disconnect(): void {
clearInterval(this.poll);
this.elementTarget.removeEventListener("mouseenter", this.handleMouseEnter.bind(this), false);
this.elementTarget.removeEventListener("mouseleave", this.handleMouseLeave.bind(this), false);
}

private handleMouseEnter(): void {
this.pollElement();
this.poll = setInterval(this.pollElement.bind(this), POLLING_RATE);
}

private pollElement(): void {
const rect = this.elementTarget.getBoundingClientRect();
if(!this.rectEqual(this.rect, rect)) {
this.rect = rect;
this.callback(this.rect);
}
}

private handleMouseLeave(): void {
this.pollElement();
clearInterval(this.poll);
}

public rectEqual(prev: DOMRectReadOnly, curr: DOMRectReadOnly): boolean {
return prev.width === curr.width &&
prev.height === curr.height &&
prev.top === curr.top &&
prev.left === curr.left;
}
}
6 changes: 3 additions & 3 deletions src/renderer/Viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Camera} from './Camera';
import {Graph} from '../graph/Graph';
import {MouseHandler} from '../UX/mouse/MouseHandler';
import {ColorRegistry} from './ColorRegistry';
import RectObserver from './RectObserver';

export class Viewport {
public readonly element: HTMLElement;
Expand Down Expand Up @@ -69,9 +70,8 @@ export class Viewport {

this.camera = new Camera(this.size);

const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]): void => {
const canvasEntry = entries[0];
this.rect = canvasEntry.contentRect;
const resizeObserver = new RectObserver((rect): void => {
this.rect = rect;
this.context.resize(this.rect.width * this.pixelRatio, this.rect.height * this.pixelRatio);
vec2.set(this.size, this.canvas.width, this.canvas.height);
this.camera.viewportSize = this.size;
Expand Down

0 comments on commit 7e4465a

Please sign in to comment.