diff --git a/apps/demo-free-layout/src/components/comment/components/resize-area.tsx b/apps/demo-free-layout/src/components/comment/components/resize-area.tsx index 8f12745e..f2683c75 100644 --- a/apps/demo-free-layout/src/components/comment/components/resize-area.tsx +++ b/apps/demo-free-layout/src/components/comment/components/resize-area.tsx @@ -1,6 +1,6 @@ import { CSSProperties, type FC } from 'react'; -import { useNodeRender, usePlayground } from '@flowgram.ai/free-layout-editor'; +import { MouseTouchEvent, useNodeRender, usePlayground } from '@flowgram.ai/free-layout-editor'; import type { CommentEditorModel } from '../model'; @@ -26,23 +26,27 @@ export const ResizeArea: FC = (props) => { const { selectNode } = useNodeRender(); - const handleMouseDown = (mouseDownEvent: React.MouseEvent) => { - mouseDownEvent.preventDefault(); - mouseDownEvent.stopPropagation(); + const handleResizeStart = ( + startResizeEvent: React.MouseEvent | React.TouchEvent | MouseEvent + ) => { + MouseTouchEvent.preventDefault(startResizeEvent); + startResizeEvent.stopPropagation(); if (!onResize) { return; } const { resizing, resizeEnd } = onResize(); model.setFocus(false); - selectNode(mouseDownEvent); + selectNode(startResizeEvent as React.MouseEvent); playground.node.focus(); // 防止节点无法被删除 - const startX = mouseDownEvent.clientX; - const startY = mouseDownEvent.clientY; + const { clientX: startX, clientY: startY } = MouseTouchEvent.getEventCoord( + startResizeEvent as MouseEvent + ); - const handleMouseMove = (mouseMoveEvent: MouseEvent) => { - const deltaX = mouseMoveEvent.clientX - startX; - const deltaY = mouseMoveEvent.clientY - startY; + const handleResizing = (mouseMoveEvent: MouseEvent | TouchEvent) => { + const { clientX: moveX, clientY: moveY } = MouseTouchEvent.getEventCoord(mouseMoveEvent); + const deltaX = moveX - startX; + const deltaY = moveY - startY; const delta = getDelta?.({ x: deltaX, y: deltaY }); if (!delta || !resizing) { return; @@ -50,16 +54,22 @@ export const ResizeArea: FC = (props) => { resizing(delta); }; - const handleMouseUp = () => { + const handleResizeEnd = () => { resizeEnd(); - document.removeEventListener('mousemove', handleMouseMove); - document.removeEventListener('mouseup', handleMouseUp); - document.removeEventListener('click', handleMouseUp); + document.removeEventListener('mousemove', handleResizing); + document.removeEventListener('mouseup', handleResizeEnd); + document.removeEventListener('click', handleResizeEnd); + document.removeEventListener('touchmove', handleResizing); + document.removeEventListener('touchend', handleResizeEnd); + document.removeEventListener('touchcancel', handleResizeEnd); }; - document.addEventListener('mousemove', handleMouseMove); - document.addEventListener('mouseup', handleMouseUp); - document.addEventListener('click', handleMouseUp); + document.addEventListener('mousemove', handleResizing); + document.addEventListener('mouseup', handleResizeEnd); + document.addEventListener('click', handleResizeEnd); + document.addEventListener('touchmove', handleResizing, { passive: false }); + document.addEventListener('touchend', handleResizeEnd); + document.addEventListener('touchcancel', handleResizeEnd); }; return ( @@ -67,7 +77,8 @@ export const ResizeArea: FC = (props) => { className="workflow-comment-resize-area" style={style} data-flow-editor-selectable="false" - onMouseDown={handleMouseDown} + onMouseDown={handleResizeStart} + onTouchStart={handleResizeStart} /> ); }; diff --git a/apps/demo-free-layout/src/components/tools/comment.tsx b/apps/demo-free-layout/src/components/tools/comment.tsx index e6404e02..ba97f049 100644 --- a/apps/demo-free-layout/src/components/tools/comment.tsx +++ b/apps/demo-free-layout/src/components/tools/comment.tsx @@ -36,14 +36,17 @@ export const Comment = () => { async (mouseEvent: React.MouseEvent) => { setTooltipVisible(false); const canvasPosition = calcNodePosition(mouseEvent); - // 创建节点 + // create comment node - 创建节点 const node = document.createWorkflowNodeByType(WorkflowNodeType.Comment, canvasPosition); - // 等待节点渲染 + // wait comment node render - 等待节点渲染 await delay(16); - // 选中节点 + // select comment node - 选中节点 selectService.selectNode(node); - // 开始拖拽 - dragService.startDragSelectedNodes(mouseEvent); + // maybe touch event - 可能是触摸事件 + if (mouseEvent.detail !== 0) { + // start drag -开始拖拽 + dragService.startDragSelectedNodes(mouseEvent); + } }, [selectService, calcNodePosition, document, dragService] ); diff --git a/packages/canvas-engine/core/src/core/layer/playground-layer.ts b/packages/canvas-engine/core/src/core/layer/playground-layer.ts index 1581a427..ba2fc7cb 100644 --- a/packages/canvas-engine/core/src/core/layer/playground-layer.ts +++ b/packages/canvas-engine/core/src/core/layer/playground-layer.ts @@ -145,6 +145,12 @@ export class PlaygroundLayer extends Layer { // 这里必须监听 NORMAL_LAYER,该图层最先触发 PipelineLayerPriority.NORMAL_LAYER ), + this.listenPlaygroundEvent('touchend', (e: TouchEvent) => { + this.options.hoverService?.clearHovered(); + }), + this.listenPlaygroundEvent('touchcancel', (e: TouchEvent) => { + this.options.hoverService?.clearHovered(); + }), this.listenPlaygroundEvent( 'mousedown', (e: MouseEvent) => { diff --git a/packages/plugins/minimap-plugin/src/component.tsx b/packages/plugins/minimap-plugin/src/component.tsx index 61821af2..b759fcc7 100644 --- a/packages/plugins/minimap-plugin/src/component.tsx +++ b/packages/plugins/minimap-plugin/src/component.tsx @@ -84,6 +84,12 @@ export const MinimapRender: React.FC = (props) => { onMouseLeave={() => { service.setActivate(false); }} + onTouchStartCapture={() => { + service.setActivate(true); + }} + onTouchEndCapture={() => { + service.setActivate(false); + }} > ); diff --git a/packages/plugins/minimap-plugin/src/service.ts b/packages/plugins/minimap-plugin/src/service.ts index 74a1be2b..84531739 100644 --- a/packages/plugins/minimap-plugin/src/service.ts +++ b/packages/plugins/minimap-plugin/src/service.ts @@ -4,7 +4,7 @@ import { Disposable, DisposableCollection, IPoint, Rectangle } from '@flowgram.a import { FlowNodeEntity, FlowNodeTransformData } from '@flowgram.ai/document'; import { FlowNodeBaseType } from '@flowgram.ai/document'; import { FlowDocument } from '@flowgram.ai/document'; -import { EntityManager, PlaygroundConfigEntity } from '@flowgram.ai/core'; +import { EntityManager, MouseTouchEvent, PlaygroundConfigEntity } from '@flowgram.ai/core'; import type { MinimapRenderContext, MinimapServiceOptions, MinimapCanvasStyle } from './type'; import { MinimapDraw } from './draw'; @@ -312,26 +312,29 @@ export class FlowMinimapService { private addEventListeners(): void { this.canvas.addEventListener('wheel', this.handleWheel); this.canvas.addEventListener('mousedown', this.handleStartDrag); + this.canvas.addEventListener('touchstart', this.handleStartDrag, { passive: false }); this.canvas.addEventListener('mousemove', this.handleCursor); } private removeEventListeners(): void { this.canvas.removeEventListener('wheel', this.handleWheel); this.canvas.removeEventListener('mousedown', this.handleStartDrag); + this.canvas.removeEventListener('touchstart', this.handleStartDrag); this.canvas.removeEventListener('mousemove', this.handleCursor); } private handleWheel = (event: WheelEvent): void => {}; - private handleStartDrag = (event: MouseEvent): void => { - event.preventDefault(); + private handleStartDrag = (event: MouseEvent | TouchEvent): void => { + MouseTouchEvent.preventDefault(event); event.stopPropagation(); const renderContext = this.createRenderContext(); const { viewRect, scale, offset } = renderContext; const canvasRect = this.canvas.getBoundingClientRect(); + const { clientX, clientY } = MouseTouchEvent.getEventCoord(event); const mousePoint: IPoint = { - x: event.clientX - canvasRect.left, - y: event.clientY - canvasRect.top, + x: clientX - canvasRect.left, + y: clientY - canvasRect.top, }; const viewRectOnCanvas = this.rectOnCanvas({ @@ -344,20 +347,26 @@ export class FlowMinimapService { } this.isDragging = true; this.dragStart = mousePoint; + // click document.addEventListener('mousemove', this.handleDragging); document.addEventListener('mouseup', this.handleEndDrag); + // touch + document.addEventListener('touchmove', this.handleDragging, { passive: false }); + document.addEventListener('touchend', this.handleEndDrag); + document.addEventListener('touchcancel', this.handleEndDrag); }; - private handleDragging = (event: MouseEvent): void => { + private handleDragging = (event: MouseEvent | TouchEvent): void => { if (!this.isDragging || !this.dragStart) return; - event.preventDefault(); + MouseTouchEvent.preventDefault(event); event.stopPropagation(); const renderContext = this.createRenderContext(); const { scale } = renderContext; const canvasRect = this.canvas.getBoundingClientRect(); - const mouseX = event.clientX - canvasRect.left; - const mouseY = event.clientY - canvasRect.top; + const { clientX, clientY } = MouseTouchEvent.getEventCoord(event); + const mouseX = clientX - canvasRect.left; + const mouseY = clientY - canvasRect.top; const deltaX = (mouseX - this.dragStart.x) / scale; const deltaY = (mouseY - this.dragStart.y) / scale; @@ -368,11 +377,16 @@ export class FlowMinimapService { this.render(); }; - private handleEndDrag = (event: MouseEvent): void => { - event.preventDefault(); + private handleEndDrag = (event: MouseEvent | TouchEvent): void => { + MouseTouchEvent.preventDefault(event); event.stopPropagation(); + // click document.removeEventListener('mousemove', this.handleDragging); document.removeEventListener('mouseup', this.handleEndDrag); + // touch + document.removeEventListener('touchmove', this.handleDragging); + document.removeEventListener('touchend', this.handleEndDrag); + document.removeEventListener('touchcancel', this.handleEndDrag); this.isDragging = false; this.dragStart = undefined; this.setActivate(this.isMouseInCanvas(event)); @@ -404,13 +418,14 @@ export class FlowMinimapService { } }; - private isMouseInCanvas(event: MouseEvent): boolean { + private isMouseInCanvas(event: MouseEvent | TouchEvent): boolean { const canvasRect = this.canvas.getBoundingClientRect(); + const { clientX, clientY } = MouseTouchEvent.getEventCoord(event); return ( - event.clientX >= canvasRect.left && - event.clientX <= canvasRect.right && - event.clientY >= canvasRect.top && - event.clientY <= canvasRect.bottom + clientX >= canvasRect.left && + clientX <= canvasRect.right && + clientY >= canvasRect.top && + clientY <= canvasRect.bottom ); }