From 8ecf36fc5e58cb4267249c2afdce6482b21c5509 Mon Sep 17 00:00:00 2001 From: Bela Bohlender Date: Tue, 25 Jun 2024 15:30:40 +0200 Subject: [PATCH] fix: scrolling on mobile is cancelled --- packages/uikit/src/components/container.ts | 16 ++++++++------- packages/uikit/src/components/image.ts | 22 +++++++++++--------- packages/uikit/src/components/root.ts | 24 ++++++++++++---------- packages/uikit/src/components/svg.ts | 18 +++++++++------- packages/uikit/src/events.ts | 2 +- packages/uikit/src/scroll.ts | 14 +++++++++---- 6 files changed, 56 insertions(+), 40 deletions(-) diff --git a/packages/uikit/src/components/container.ts b/packages/uikit/src/components/container.ts index 716be7aa..8a15e05a 100644 --- a/packages/uikit/src/components/container.ts +++ b/packages/uikit/src/components/container.ts @@ -130,11 +130,19 @@ export function createContainer( parentContext.root.panelGroupManager, initializers, ) + const interactionPanel = createInteractionPanel( + orderInfo, + parentContext.root, + parentContext.clippingRect, + flexState.size, + initializers, + ) const scrollHandlers = computedScrollHandlers( scrollPosition, parentContext.anyAncestorScrollable, flexState, object, + interactionPanel, properties, parentContext.root, initializers, @@ -158,13 +166,7 @@ export function createContainer( orderInfo, root: parentContext.root, scrollPosition, - interactionPanel: createInteractionPanel( - orderInfo, - parentContext.root, - parentContext.clippingRect, - flexState.size, - initializers, - ), + interactionPanel, handlers: computedHandlers(style, properties, defaultProperties, hoveredSignal, activeSignal, scrollHandlers), initializers, }) diff --git a/packages/uikit/src/components/image.ts b/packages/uikit/src/components/image.ts index 92ea1802..cd1b405b 100644 --- a/packages/uikit/src/components/image.ts +++ b/packages/uikit/src/components/image.ts @@ -167,11 +167,22 @@ export function createImage( parentContext.root.panelGroupManager, initializers, ) + const interactionPanel = createImageMesh( + mergedProperties, + texture, + parentContext, + flexState, + orderInfo, + parentContext.root, + isVisible, + initializers, + ) const scrollHandlers = computedScrollHandlers( scrollPosition, parentContext.anyAncestorScrollable, flexState, object, + interactionPanel, properties, parentContext.root, initializers, @@ -187,16 +198,7 @@ export function createImage( anyAncestorScrollable: computedAnyAncestorScrollable(flexState.scrollable, parentContext.anyAncestorScrollable), initializers, handlers: computedHandlers(style, properties, defaultProperties, hoveredSignal, activeSignal, scrollHandlers), - interactionPanel: createImageMesh( - mergedProperties, - texture, - parentContext, - flexState, - orderInfo, - parentContext.root, - isVisible, - initializers, - ), + interactionPanel, clippingRect: computedClippingRect( globalMatrix, flexState, diff --git a/packages/uikit/src/components/root.ts b/packages/uikit/src/components/root.ts index fe64549d..c8956b1c 100644 --- a/packages/uikit/src/components/root.ts +++ b/packages/uikit/src/components/root.ts @@ -185,16 +185,6 @@ export function createRoot( initializers, ) - const scrollHandlers = computedScrollHandlers( - scrollPosition, - undefined, - flexState, - object, - properties, - ctx, - initializers, - ) - setupLayoutListeners(style, properties, flexState.size, initializers) const gylphGroupManager = new GlyphGroupManager(renderOrder, depthTest, pixelSize, ctx, object, initializers) @@ -214,6 +204,18 @@ export function createRoot( size: flexState.size, }) + const interactionPanel = createInteractionPanel(orderInfo, rootCtx, undefined, flexState.size, initializers) + const scrollHandlers = computedScrollHandlers( + scrollPosition, + undefined, + flexState, + object, + interactionPanel, + properties, + ctx, + initializers, + ) + return Object.assign(flexState, { scrollPosition, mergedProperties, @@ -223,7 +225,7 @@ export function createRoot( node, orderInfo, initializers, - interactionPanel: createInteractionPanel(orderInfo, rootCtx, undefined, flexState.size, initializers), + interactionPanel, handlers: computedHandlers(style, properties, defaultProperties, hoveredSignal, activeSignal, scrollHandlers), root: rootCtx, }) diff --git a/packages/uikit/src/components/svg.ts b/packages/uikit/src/components/svg.ts index b56033db..d7673a66 100644 --- a/packages/uikit/src/components/svg.ts +++ b/packages/uikit/src/components/svg.ts @@ -168,11 +168,21 @@ export function createSvg( parentContext.root.panelGroupManager, initializers, ) + + const interactionPanel = createInteractionPanel( + orderInfo, + parentContext.root, + parentContext.clippingRect, + flexState.size, + initializers, + ) + const scrollHandlers = computedScrollHandlers( scrollPosition, parentContext.anyAncestorScrollable, flexState, object, + interactionPanel, properties, parentContext.root, initializers, @@ -199,13 +209,7 @@ export function createSvg( initializers, centerGroup, handlers: computedHandlers(style, properties, defaultProperties, hoveredSignal, activeSignal, scrollHandlers), - interactionPanel: createInteractionPanel( - orderInfo, - parentContext.root, - parentContext.clippingRect, - flexState.size, - initializers, - ), + interactionPanel, }) } diff --git a/packages/uikit/src/events.ts b/packages/uikit/src/events.ts index 6d6a32a3..977c4862 100644 --- a/packages/uikit/src/events.ts +++ b/packages/uikit/src/events.ts @@ -1,4 +1,4 @@ -import { Intersection } from 'three' +import { Intersection, Object3D } from 'three' export type ThreeEvent = Intersection & { nativeEvent: TSourceEvent diff --git a/packages/uikit/src/scroll.ts b/packages/uikit/src/scroll.ts index 6904a84d..9e0873d8 100644 --- a/packages/uikit/src/scroll.ts +++ b/packages/uikit/src/scroll.ts @@ -1,7 +1,7 @@ import { ReadonlySignal, Signal, computed, effect, signal } from '@preact/signals-core' -import { Matrix4, Object3D, Vector2, Vector2Tuple, Vector3, Vector4Tuple } from 'three' -import { FlexNode, FlexNodeState, Inset } from './flex/node.js' -import { ColorRepresentation, Initializers, Subscriptions, computedBorderInset } from './utils.js' +import { Matrix4, Mesh, Vector2, Vector2Tuple, Vector3, Vector4Tuple } from 'three' +import { FlexNodeState, Inset } from './flex/node.js' +import { ColorRepresentation, Initializers, computedBorderInset } from './utils.js' import { ClippingRect } from './clipping.js' import { clamp } from 'three/src/math/MathUtils.js' import { PanelProperties, createInstancedPanel } from './panel/instanced-panel.js' @@ -74,6 +74,7 @@ export function computedScrollHandlers( anyAncestorScrollable: Signal | undefined, { scrollable, maxScrollPosition }: FlexNodeState, object: Object3DRef, + interactionPanel: Mesh, listeners: Signal, root: Pick, initializers: Initializers, @@ -199,7 +200,12 @@ export function computedScrollHandlers( object.current!.worldToLocal(interaction.point.copy(point)) }, onPointerUp: onPointerFinish, - onPointerLeave: onPointerFinish, + onPointerOut: (e: ThreeEvent) => { + if (e.object != interactionPanel) { + return + } + onPointerFinish(e) + }, onPointerCancel: onPointerFinish, onPointerMove: (event) => { const prevInteraction = downPointerMap.get(event.nativeEvent.pointerId)