Fabric Canvas加载JSON后如何实现对象随画布尺寸自适应缩放?
解决Fabric.js对象跨画布尺寸自适应缩放的问题
这个问题我之前也碰到过,Fabric.js默认保存的是对象的绝对像素值(left、top、width、height),换画布尺寸自然会出现错位或超出的情况。核心解决思路是把对象的位置和尺寸从绝对单位转换成相对于原画布的比例,加载时再根据新画布的尺寸还原成适配后的绝对单位。
步骤1:保存画布JSON时附加原画布尺寸
保存的时候,我们需要在生成的JSON里额外记录原画布的宽高,这样加载时才有参考基准:
// 假设你的画布实例是canvas const originalCanvasWidth = canvas.width; const originalCanvasHeight = canvas.height; // 生成包含画布尺寸的自定义JSON const canvasJSON = JSON.stringify({ canvasSize: { width: originalCanvasWidth, height: originalCanvasHeight }, objects: canvas.toJSON(['left', 'top', 'width', 'height', 'src', 'type', 'fill']) // 按需保留对象属性 }); // 保存到本地或服务器,这里用localStorage举例 localStorage.setItem('myCanvasData', canvasJSON);
步骤2:加载JSON时按比例缩放对象
加载时,先解析JSON提取原画布尺寸,再计算新画布与原画布的缩放比例,最后遍历所有对象调整位置和尺寸:
// 假设新画布的目标尺寸是600x600 const newWidth = 600; const newHeight = 600; // 读取保存的JSON const savedJSON = JSON.parse(localStorage.getItem('myCanvasData')); const originalSize = savedJSON.canvasSize; // 计算宽高方向的缩放比例 const scaleX = newWidth / originalSize.width; const scaleY = newHeight / originalSize.height; // 初始化新画布 const newCanvas = new fabric.Canvas('new-canvas', { width: newWidth, height: newHeight }); // 遍历所有对象,调整位置和尺寸 savedJSON.objects.forEach(obj => { // 调整位置:原left/top乘以对应方向的缩放比例 obj.left *= scaleX; obj.top *= scaleY; // 调整尺寸:原width/height乘以对应方向的缩放比例 obj.width *= scaleX; obj.height *= scaleY; // 如果对象有缩放属性(比如之前手动调整过scaleX/Y),也需要同步缩放 if (obj.scaleX) obj.scaleX *= scaleX; if (obj.scaleY) obj.scaleY *= scaleY; }); // 加载调整后的对象到新画布并渲染 newCanvas.loadFromJSON(savedJSON, () => { newCanvas.renderAll(); });
额外优化建议
- 保持整体比例:如果不想拉伸对象,可以取宽高比例的最小值作为统一缩放因子,比如
const scale = Math.min(scaleX, scaleY),所有属性都乘以这个值,还可以额外调整对象位置让它居中显示。 - 锚点适配:如果对象设置了非左上角的锚点(比如
originX: 'center'),调整位置时要计算锚点偏移量,比如原中心位置是(originalSize.width/2, originalSize.height/2),新中心是(newWidth/2, newHeight/2),对象新位置应该是新中心加上原偏移量乘以缩放比例。 - 属性完整性:调用
toJSON()时要确保保留所有需要的样式属性(比如颜色、透明度),避免加载后丢失视觉效果。
内容的提问来源于stack exchange,提问作者Pierre Olivier Tran
相关产品推荐
相关产品推荐

