Skip to content

Commit

Permalink
improve hit test
Browse files Browse the repository at this point in the history
  • Loading branch information
Moon-DaeSeung committed Mar 22, 2024
1 parent a99e168 commit 6e67b0f
Show file tree
Hide file tree
Showing 23 changed files with 576 additions and 408 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"predocs",
"prestory",
"publint",
"renderobject",
"rgba",
"Shiki",
"tailwindcss",
Expand Down
21 changes: 14 additions & 7 deletions packages/docs/src/components/diagram/widget/InteractiveViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ class InteractiveViewportState extends State<InteractiveViewport> {

if (typeof window === "undefined") return;
this.view.addEventListener("wheel", this.handleWheel);
this.view.addEventListener("mousedown", this.handleDragStart);
this.view.parentElement!.addEventListener(
"mousedown",
this.handleDragStart,
);
this.view.setAttribute("preserveAspectRatio", "none");
document.addEventListener("mousemove", this.handleDragMove);
document.addEventListener("mouseup", this.handleDragEnd);
Expand All @@ -56,15 +59,18 @@ class InteractiveViewportState extends State<InteractiveViewport> {

dispose(): void {
this.view.removeEventListener("wheel", this.handleWheel);
this.view.removeEventListener("mousedown", this.handleDragStart);
this.view.parentElement!.removeEventListener(
"mousedown",
this.handleDragStart,
);
document.removeEventListener("mousemove", this.handleDragMove);
document.removeEventListener("mouseup", this.handleDragEnd);
this.resizeObserver.disconnect();
}

handleDragStart = (e: MouseEvent) => {
this.dragPoint = new Offset({ x: e.x, y: e.y });
this.view.style.cursor = "grabbing"; // Change cursor shape to 'grabbing'
this.view.style.cursor = "grabbing";
};

handleDragMove = (e: MouseEvent) => {
Expand Down Expand Up @@ -146,11 +152,12 @@ class InteractiveViewportState extends State<InteractiveViewport> {
}

private notifyViewportChange() {
this.view.setAttribute(
"viewBox",
`${this.viedBox.x} ${this.viedBox.y} ${this.viedBox.width} ${this.viedBox.height}`,
);
const scale = this.controller.getScale();
this.element.renderContext.setViewport({
translation: { x: -this.viedBox.x, y: -this.viedBox.y },
scale,
});

this.controller.changeRootRect({
left: -this.viedBox.x,
top: -this.viedBox.y,
Expand Down
6 changes: 5 additions & 1 deletion packages/flitter-svelte/src/lib/Widget.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
runner.onMount({
resizeTarget: containerEl
});
return () => {
runner.dispose();
};
});
</script>

Expand All @@ -66,6 +70,6 @@
}
.flitter {
width: 100%;
height: 100%
height: 100%;
}
</style>
13 changes: 0 additions & 13 deletions packages/flitter/src/component/Tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,6 @@ class ToolTipState extends State<ToolTip> {
clipped: false,
children: [
GestureDetector({
bubble: {
mousedown: true,
mouseenter: true,
mouseleave: true,
mousemove: true,
mouseover: true,
mouseup: true,
click: true,
drag: true,
dragend: true,
dragstart: true,
wheel: true,
},
cursor: "default",
child: this.widget.child,
onMouseEnter: () => {
Expand Down
127 changes: 24 additions & 103 deletions packages/flitter/src/component/base/BaseGestureDetector.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { RenderObjectElement } from "../../element";
import SingleChildRenderObject from "../../renderobject/SingleChildRenderObject";
import { TypedObject, assert, createUniqueId } from "../../utils";
import { assert, createUniqueId } from "../../utils";
import type { PaintContext } from "../../utils/type";
import SingleChildRenderObjectWidget from "../../widget/SingleChildRenderObjectWidget";
import type Widget from "../../widget/Widget";
Expand Down Expand Up @@ -71,7 +71,6 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
onDragEnd: (e: MouseEvent) => void;
onWheel: (e: WheelEvent) => void;
cursor: Cursor;
bubble: Bubble;
constructor({
child,
onClick,
Expand All @@ -86,7 +85,6 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
onDragEnd,
onDragMove,
onDragStart,
bubble = {},
onWheel,
}: {
child?: Widget;
Expand All @@ -103,6 +101,11 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
onWheel?: (e: WheelEvent) => void;
cursor?: Cursor;
key?: any;

/**
* @deprecated
* This prop is no longer used. Please use e.stopPropagation() instead.
*/
bubble?: Partial<Bubble>;
}) {
super({ child, key });
Expand All @@ -118,20 +121,6 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
this.onDragEnd = onDragEnd ?? emptyCallback;
this.onWheel = onWheel ?? emptyCallback;
this.cursor = cursor ?? "pointer";
this.bubble = {
mousedown: false,
mouseenter: false,
mouseleave: false,
mousemove: false,
mouseover: false,
mouseup: false,
click: false,
wheel: false,
dragstart: false,
dragend: false,
drag: false,
...bubble,
};
}

override createRenderObject(): RenderGestureDetector {
Expand All @@ -148,7 +137,6 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
onDragEnd: this.onDragEnd,
onWheel: this.onWheel,
cursor: this.cursor,
bubble: this.bubble,
});
}

Expand All @@ -161,21 +149,13 @@ class BaseGestureDetector extends SingleChildRenderObjectWidget {
renderObject.onDragStart = this.onDragStart;
renderObject.onDragMove = this.onDragMove;
renderObject.onDragEnd = this.onDragEnd;
renderObject.bubble = this.bubble;
renderObject.onWheel = this.onWheel;
}
}

class RenderGestureDetector extends SingleChildRenderObject {
export class RenderGestureDetector extends SingleChildRenderObject {
isRenderGestureDetector = true;
private id = createUniqueId();
private _bubble: Bubble;
get bubble(): Bubble {
return this._bubble;
}
set bubble(prop: Bubble) {
this._bubble = prop;
}
id = createUniqueId();
private _cursor: Cursor;
get cursor(): Cursor {
return this._cursor;
Expand Down Expand Up @@ -286,7 +266,6 @@ class RenderGestureDetector extends SingleChildRenderObject {
onDragMove,
onDragStart,
cursor,
bubble,
onWheel,
}: {
onClick: MouseEventCallback;
Expand All @@ -301,7 +280,6 @@ class RenderGestureDetector extends SingleChildRenderObject {
onDragEnd: MouseEventCallback;
onWheel: (e: WheelEvent) => void;
cursor: Cursor;
bubble: Bubble;
}) {
super({ isPainter: true });
this._onClick = onClick;
Expand All @@ -316,44 +294,12 @@ class RenderGestureDetector extends SingleChildRenderObject {
this._onDragStart = onDragStart;
this._onWheel = onWheel;
this._cursor = cursor;
this._bubble = bubble;
}
private get listeners(): Record<
EventType,
MouseEventCallback | ((e: WheelEvent) => void)
> {
const listeners = {
click: this.onClick,
mousedown: this.onMouseDown,
mousemove: this.onMouseMove,
mouseup: this.onMouseUp,
mouseover: this.onMouseOver,
mouseenter: this.onMouseEnter,
mouseleave: this.onMouseLeave,
wheel: this.onWheel,
dragstart: this.onDragStart,
drag: this.onDragMove,
dragend: this.onDragEnd,
};

return TypedObject.keys(listeners).reduce(
(acc, key) => {
acc[key] = (e: any) => {
if (this.bubble[key]) {
this.dispatchParent(e);
}
listeners[key]?.(e);
};

return acc;
},
{} as Record<EventType, MouseEventCallback | ((e: WheelEvent) => void)>,
);
}

attach(ownerElement: RenderObjectElement): void {
super.attach(ownerElement);
this.addEventListeners();
this.renderOwner.hitTestDispatcher.addDetector(this);
}

dispose(context: PaintContext): void {
Expand All @@ -364,6 +310,7 @@ class RenderGestureDetector extends SingleChildRenderObject {
globalDragBackend = null;
}
super.dispose(context);
this.renderOwner.hitTestDispatcher.removeDetector(this);
}

private removeEventListeners() {
Expand All @@ -374,26 +321,14 @@ class RenderGestureDetector extends SingleChildRenderObject {
const isBrowser = typeof window !== "undefined";
if (!isBrowser) return;

const {
svgEls: { rect },
} = this.resolveSvgEl();

const dragBackend = getSingletonDragBackend();
dragBackend.isSetup || dragBackend.setup();
backendRefCount++;

const { drag, dragend, dragstart, ...restListeners } = this.listeners;

dragBackend.connectDragSource(this.id, rect, {
onDragStart: dragstart,
onDragMove: drag,
onDragEnd: dragend,
});

TypedObject.entries(restListeners).forEach(([type, listener]) => {
rect.addEventListener(type, (e: any) => {
listener(e);
});
dragBackend.connectDragSource(this, {
onDragStart: this.onDragStart,
onDragMove: this.onDragMove,
onDragEnd: this.onDragEnd,
});
}

Expand All @@ -411,22 +346,6 @@ class RenderGestureDetector extends SingleChildRenderObject {
rect,
};
}

dispatch(e: Event) {
this.listeners[e.type]?.(e);
}

dispatchParent(e: Event) {
let parent = this.parent;

while (parent != null) {
if ((parent as RenderGestureDetector)?.isRenderGestureDetector) {
(parent as RenderGestureDetector).dispatch(e);
break;
}
parent = parent.parent;
}
}
}

type MouseEventCallback = (event: MouseEvent) => void;
Expand Down Expand Up @@ -475,9 +394,12 @@ class DragBackend {
this.activeDragSourceId = null;
};

setActiveDragSourceId(sourceId: string) {
this.activeDragSourceId = sourceId;
}

public connectDragSource(
sourceId: string,
node: SVGElement,
detector: RenderGestureDetector,
{
onDragStart = emptyCallback,
onDragMove = emptyCallback,
Expand All @@ -488,14 +410,13 @@ class DragBackend {
onDragEnd?: (e: MouseEvent) => void;
} = {},
) {
this.dragStartListener[sourceId] = e => {
this.activeDragSourceId = sourceId;
const sourceId = detector.id;
const onMouseDown = detector.onMouseDown;
detector.onMouseDown = (e: MouseEvent) => {
onMouseDown(e);
this.setActiveDragSourceId(sourceId);
onDragStart(e);
};
node.addEventListener(
"mousedown",
this.dragStartListener[sourceId].bind(this),
);
this.dragMoveListener[sourceId] = e => {
onDragMove(e);
};
Expand Down
3 changes: 1 addition & 2 deletions packages/flitter/src/element/Element.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type RenderObject from "../renderobject/RenderObject";
import type { RenderContext } from "../runApp";
import type { BuildOwner, Scheduler } from "../scheduler";
import type { GlobalKey } from "../scheduler";
import type { BuildOwner, Scheduler, GlobalKey } from "../scheduler";
import Widget from "../widget/Widget";

class Element {
Expand Down
Loading

0 comments on commit 6e67b0f

Please sign in to comment.