Rete.js移动端适配:触摸设备上的流程图交互优化

Rete.js移动端适配:触摸设备上的流程图交互优化

【免费下载链接】rete JavaScript framework for visual programming 【免费下载链接】rete 项目地址: https://gitcode.com/gh_mirrors/re/rete

你是否在手机上尝试过拖动流程图节点,却发现节点像失控的陀螺一样乱窜?或者想精确连接两个端口时,手指总是挡住目标位置?作为一款JavaScript可视化编程框架(JavaScript framework for visual programming),Rete.js在桌面端提供了流畅的节点编辑体验,但触摸设备的交互差异常让开发者头疼。本文将通过5个实用技巧,帮你解决移动端适配的核心痛点,让你的流程图应用在手机和平板上同样专业易用。

触摸交互三大痛点与解决方案

移动端适配的本质是解决触摸与鼠标的物理差异:手指触点面积是鼠标指针的20倍以上,且缺乏悬停状态。通过分析src/editor.ts的核心事件系统,我们可以针对性优化。

1. 节点拖动:从"漂移"到"粘手"

问题表现:拖动节点时出现明显延迟或偏移,手指离开屏幕后节点继续移动。

解决方案:实现触摸专用的拖动阈值与惯性控制。通过监听touchstarttouchmovetouchend事件,在src/utils.ts中扩展手势处理工具:

// 触摸拖动优化示例(需添加到src/utils.ts)
export function createTouchHandler(editor) {
  let startX, startY, isDragging = false;
  const TOUCH_THRESHOLD = 10; // 10px内视为点击而非拖动
  
  return {
    onTouchStart(e) {
      const touch = e.touches[0];
      startX = touch.clientX;
      startY = touch.clientY;
    },
    onTouchMove(e) {
      const touch = e.touches[0];
      const dx = touch.clientX - startX;
      const dy = touch.clientY - startY;
      
      if (!isDragging && Math.sqrt(dx*dx + dy*dy) > TOUCH_THRESHOLD) {
        isDragging = true;
        editor.emit('touchdragstart', { dx, dy }); // 触发拖动开始事件
      }
      
      if (isDragging) {
        e.preventDefault(); // 阻止页面滚动
        editor.emit('touchdrag', { dx, dy }); // 触发拖动事件
      }
    },
    onTouchEnd() {
      isDragging = false;
      editor.emit('touchdragend');
    }
  };
}

2. 端口点击:从"误触"到"精准"

问题表现:手指点击节点端口时,常误触相邻端口或触发节点拖动。

解决方案:在src/presets/classic.ts中修改Port类,增加触摸友好的交互区域:

// 端口触摸优化(修改src/presets/classic.ts第29行)
export class Port<S extends Socket> {
  id: PortId;
  index?: number;
  // 新增触摸相关属性
  touchArea: { x: number, y: number, width: number, height: number }; // 触摸热区
  
  constructor(public socket: S, public label?: string, public multipleConnections?: boolean) {
    this.id = getUID();
    // 设置扩大的触摸热区(比视觉尺寸大40%)
    this.touchArea = { x: -10, y: -10, width: 40, height: 40 };
  }
}

3. 连接绘制:从"抖动"到"流畅"

问题表现:触摸绘制连接时线条抖动严重,难以准确连接到目标端口。

解决方案:实现连接路径的平滑算法,在src/presets/classic.tsConnection类中添加贝塞尔曲线优化:

// 连接曲线平滑(修改src/presets/classic.ts第250行)
export class Connection<Source extends Node, Target extends Node> implements ConnectionBase {
  // ... 现有代码 ...
  
  // 生成平滑连接路径
  getPath() {
    const sourcePos = this.getSourcePosition();
    const targetPos = this.getTargetPosition();
    
    // 使用贝塞尔曲线减少触摸抖动影响
    const controlPointX = (sourcePos.x + targetPos.x) / 2;
    return `M ${sourcePos.x} ${sourcePos.y} 
            Q ${controlPointX} ${sourcePos.y}, ${controlPointX} ${(sourcePos.y + targetPos.y)/2}
            Q ${controlPointX} ${targetPos.y}, ${targetPos.x} ${targetPos.y}`;
  }
}

界面适配:让控件"呼吸"的响应式设计

节点尺寸自适应

根据屏幕宽度动态调整节点大小,在src/presets/classic.tsNode类中添加响应式逻辑:

// 响应式节点(修改src/presets/classic.ts第173行)
export class Node<Inputs, Outputs, Controls> implements NodeBase {
  // ... 现有代码 ...
  
  constructor(public label: string) {
    this.id = getUID();
    this.resize(); // 初始化尺寸
    window.addEventListener('resize', () => this.resize());
  }
  
  resize() {
    const isMobile = window.innerWidth < 768;
    this.width = isMobile ? window.innerWidth * 0.8 : 200; // 移动端占屏幕宽度80%
    this.height = isMobile ? 120 : 100;
    this.portSize = isMobile ? 24 : 18; // 端口尺寸增大33%
  }
}

触摸友好的控件库

扩展src/presets/classic.ts中的InputControl,提供更大的交互区域和适合触摸的控件类型:

// 触摸优化控件(修改src/presets/classic.ts第141行)
export class InputControl<T extends 'text' | 'number' | 'slider' | 'toggle', N = ...> extends Control {
  // ... 现有代码 ...
  
  constructor(public type: T, public options?: InputControlOptions<N>) {
    super();
    this.id = getUID();
    this.readonly = options?.readonly ?? false;
    
    // 根据类型设置触摸友好的样式
    this.style = type === 'slider' ? {
      height: '40px', // 滑块高度增加
      padding: '10px',
      touchAction: 'none' // 阻止浏览器默认触摸行为
    } : type === 'toggle' ? {
      width: '60px',
      height: '30px'
    } : {
      minHeight: '44px', // 符合移动设计标准的控件高度
      fontSize: '16px', // 增大字体
      padding: '10px'
    };
    
    if (typeof options?.initial !== 'undefined') this.value = options.initial;
  }
}

事件系统扩展:构建触摸优先的交互层

Rete.js的核心事件系统在src/editor.ts中实现,我们需要为其添加触摸专用事件,同时保持与现有鼠标事件的兼容性:

// 触摸事件扩展(添加到src/editor.ts第29行NodeEditor类)
class NodeEditor<Scheme extends BaseSchemes> extends Scope<Root<Scheme>> {
  // ... 现有代码 ...
  
  constructor() {
    super('NodeEditor');
    // 初始化触摸处理
    this.touchHandler = createTouchHandler(this);
    this.bindTouchEvents();
  }
  
  bindTouchEvents() {
    const container = document.getElementById('rete-container');
    if (!container) return;
    
    container.addEventListener('touchstart', e => this.touchHandler.onTouchStart(e));
    container.addEventListener('touchmove', e => this.touchHandler.onTouchMove(e), { passive: false });
    container.addEventListener('touchend', e => this.touchHandler.onTouchEnd(e));
    container.addEventListener('touchcancel', e => this.touchHandler.onTouchEnd(e));
  }
}

测试与调试:触摸设备的"千里眼"

在开发阶段模拟触摸行为至关重要。推荐使用Chrome浏览器的"设备工具栏",选择对应设备型号后测试以下场景:

  1. 双指缩放:测试画布缩放功能,确保节点和连接不会失真
  2. 触摸滚动:验证画布平移与节点拖动的冲突处理
  3. 快速点击:检查连续点击不同节点是否触发正确响应

可在test/index.test.ts中添加移动端专用测试用例:

// 移动端测试示例(添加到test/index.test.ts)
test('touch drag node', async () => {
  const editor = new NodeEditor();
  const node = new ClassicPreset.Node('test');
  await editor.addNode(node);
  
  // 模拟触摸事件
  fireTouchEvent(editor.view.container, 'touchstart', { clientX: 100, clientY: 100 });
  fireTouchEvent(editor.view.container, 'touchmove', { clientX: 150, clientY: 150 });
  fireTouchEvent(editor.view.container, 'touchend');
  
  expect(node.position.x).toBe(50); // 验证节点移动了50px
  expect(node.position.y).toBe(50);
});

完整适配清单与最佳实践

为确保适配效果,建议按以下清单检查实现:

检查项移动端要求实现方法
节点尺寸宽度≥160px,高度≥80px修改src/presets/classic.ts的Node类
端口大小直径≥24px调整Port类的renderSize属性
触摸反馈操作时有视觉反馈(如缩放/变色)添加CSS :active状态样式
事件冲突拖动时禁止页面滚动在touchmove中调用preventDefault
性能优化60fps流畅度使用requestAnimationFrame更新位置

通过以上优化,你的Rete.js应用将在移动设备上呈现专业的交互体验。核心是记住:移动端不是桌面端的缩小版,而是需要重新设计的交互范式。框架的src/index.ts提供了灵活的扩展点,你可以根据项目需求进一步定制手势系统,甚至实现多手指编辑等高级功能。现在就拿起手机测试你的应用——流畅的节点交互会让用户忘记他们是在触摸屏幕,而不是点击鼠标。

【免费下载链接】rete JavaScript framework for visual programming 【免费下载链接】rete 项目地址: https://gitcode.com/gh_mirrors/re/rete

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值