You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模拟移动触摸设备时FabricJS渲染异常问题求助

FabricJS触摸模拟下upperCanvas尺寸异常问题排查与解决

问题背景

我使用ThreeJS管理canvas0(负责缩放、平移等交互),FabricJS负责canvas1的标注功能。Chrome浏览器鼠标操作下功能正常,但通过Chrome调试器的「Toggle Device Toolbar」模拟移动触摸设备时出现异常:绘制路径时实时渲染位置错误,结束触摸后路径位置才恢复正常。

经观察:FabricJS的lowerCanvas尺寸为代码定义的256256px,但upperCanvas(用于路径创建过程中实时渲染的画布)被莫名设置为512512px。页面刷新后upperCanvas尺寸偶尔正常(此时渲染正常),但多数时候尺寸异常,硬刷新无法解决。

复现步骤

  • Chrome按F12打开调试器
  • 点击「Toggle Device Toolbar」并选择模拟设备(如iPhone SE)
  • 按F5刷新页面
  • 在canvas0上进行绘制操作

核心疑问

  1. 是什么设置了upperCanvas为512*512px?
  2. 如何手动设置upperCanvas的尺寸?目前调用fabricCanvas.setDimensions({width:256, height:256})仅能修改lowerCanvas的尺寸。

问题原因

FabricJS在触摸设备环境下,会自动根据**设备像素比(window.devicePixelRatio)**缩放upperCanvas的尺寸,以此适配高DPI屏幕。当Chrome模拟移动设备时,设备像素比被设置为2(例如iPhone SE的DPR为2),因此upperCanvas的尺寸会被自动放大为定义尺寸的2倍(256×2=512)。而代码未同步处理该缩放逻辑,导致实时渲染时坐标映射错误,触摸结束后FabricJS会重新计算坐标,所以位置恢复正常。

解决方案

1. 强制固定设备像素比

初始化FabricJS画布时,显式指定devicePixelRatio为1,阻止自动缩放upperCanvas:

const fabricCanvas = new fabric.Canvas('canvas1', {
  width: 256,
  height: 256,
  devicePixelRatio: 1 // 禁用自动DPI适配
});

2. 手动同步upperCanvas尺寸

若需要动态调整尺寸,可直接操作upperCanvas元素,同步修改其样式尺寸与画布内部尺寸:

// 获取upperCanvas元素
const upperCanvas = fabricCanvas.upperCanvasEl;
// 设置样式尺寸(控制显示大小)
upperCanvas.style.width = '256px';
upperCanvas.style.height = '256px';
// 设置画布内部像素尺寸(控制渲染精度)
upperCanvas.width = 256;
upperCanvas.height = 256;
// 触发重绘确保生效
fabricCanvas.renderAll();

3. 同步ThreeJS与FabricJS的缩放比例

由于canvas0由ThreeJS管理存在缩放平移,需确保FabricJS的画布缩放与ThreeJS视图保持一致,避免触摸坐标偏移:

// 假设threeCamera是你的ThreeJS相机实例
const zoomLevel = threeCamera.zoom;
fabricCanvas.setZoom(zoomLevel);
// 可选:同步画布位置偏移
fabricCanvas.setViewportTransform([zoomLevel, 0, 0, zoomLevel, offsetX, offsetY]);

内容的提问来源于stack exchange,提问作者Avner Moshkovitz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:00:12