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

Fabric.JS调整画布尺寸时如何保持背景图片宽高比?

解决方案

问题根源

  1. Fabric.js的setDimensions()方法不支持maxWidth和maxHeight参数,你设置的这两个值不会生效,画布只会严格按照传入的width和height渲染。
  2. 重复加载图片(原生Image和fabric.Image各加载一次)不仅冗余,还可能导致尺寸计算时机混乱。
  3. 直接将原图设为背景时未做比例缩放,导致图片被强制拉伸填满画布。

修正步骤

直接利用fabric.Image.fromURL回调中已加载完成的oImg处理,按以下逻辑实现:

  • 计算图片宽高比,算出不超过600x600的最大缩放尺寸
  • 按比例缩放背景图
  • 根据缩放后的图片尺寸设置画布大小

修正后代码

var canvas = new fabric.Canvas('canvas');

fabric.Image.fromURL(path, function(oImg) {
    const maxSize = 600;
    let scaleFactor = 1;

    // 取宽、高方向缩放比例的较小值,保证图片完全在600x600范围内
    if (oImg.width > maxSize || oImg.height > maxSize) {
        const widthScale = maxSize / oImg.width;
        const heightScale = maxSize / oImg.height;
        scaleFactor = Math.min(widthScale, heightScale);
    }

    // 按比例缩放图片
    oImg.scale(scaleFactor);

    // 设置画布尺寸为缩放后的图片尺寸
    canvas.setDimensions({
        width: oImg.width * scaleFactor,
        height: oImg.height * scaleFactor
    });

    // 设置背景图并渲染画布
    canvas.setBackgroundImage(oImg, canvas.renderAll.bind(canvas));
});

额外需求方案(画布固定600x600,图片居中不拉伸)

如果需要画布固定为600x600,图片在画布内居中显示,可改用以下代码:

var canvas = new fabric.Canvas('canvas');
// 先固定画布尺寸为600x600
canvas.setDimensions({ width: 600, height: 600 });

fabric.Image.fromURL(path, function(oImg) {
    const maxSize = 600;
    let scaleFactor = 1;

    if (oImg.width > maxSize || oImg.height > maxSize) {
        const widthScale = maxSize / oImg.width;
        const heightScale = maxSize / oImg.height;
        scaleFactor = Math.min(widthScale, heightScale);
    }

    oImg.scale(scaleFactor);
    // 让图片在画布中居中
    oImg.set({
        left: (canvas.width - oImg.width * scaleFactor) / 2,
        top: (canvas.height - oImg.height * scaleFactor) / 2
    });

    canvas.setBackgroundImage(oImg, canvas.renderAll.bind(canvas));
});

内容的提问来源于stack exchange,提问作者Davide Iori

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:41:04