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

如何在HTML5 Canvas放置图片时将图片裁剪为正方形

Canvas网格图片居中裁剪正方形方案

你当前代码出现图片拉伸变形的核心原因是使用了drawImage的简化调用形式,这种写法会强制将整张原图拉伸至指定的200*200尺寸,完全忽略原图自身宽高比。要实现无变形的正方形裁剪,需要使用drawImage的9参数完整语法,手动指定原图上的裁剪区域。

核心API说明

drawImage的9参数完整格式如下,前四个参数控制从原图上取哪个区域的内容,后四个参数控制把取到的内容画到画布的哪个位置、缩放到多大:

ctx.drawImage(
  图片对象,
  源图裁剪区域起点X坐标, 源图裁剪区域起点Y坐标, 源图裁剪区域宽度, 源图裁剪区域高度,
  画布绘制起点X坐标, 画布绘制起点Y坐标, 画布绘制区域宽度, 画布绘制区域高度
)

裁剪计算规则

要实现居中正方形裁剪(等价于CSS的object-fit: cover效果),计算逻辑非常固定:

  • 读取加载完成的图片原始宽高img.width、img.height
  • 取原始宽、高中的较小值作为正方形裁剪区域的边长,这样可以裁出原图范围内最大的正方形区域,不会出现留白
  • 计算裁剪区域的起点坐标,保证裁剪区域在原图居中:
    • 横版图片(宽度>高度):纵向从图片顶端(Y=0)开始裁剪,横向起点为 (原图宽度 - 裁剪边长) / 2,裁掉左右两侧多余部分
    • 竖版图片(高度>宽度):横向从图片左端(X=0)开始裁剪,纵向起点为 (原图高度 - 裁剪边长) / 2,裁掉上下两侧多余部分
    • 正方形图片:起点坐标为(0,0),直接取全图绘制即可

修改后可直接运行的代码

const ctx = canvas.getContext("2d");
// 单个网格单元格尺寸
const CELL_SIZE = 200;
for (let xCell = 0; xCell < 5; xCell++) {
  for (let yCell = 0; yCell < 5; yCell++) {
    const targetX = xCell * CELL_SIZE;
    const targetY = yCell * CELL_SIZE;
    const img = new Image();
    img.onload = function() {
      const originW = img.width;
      const originH = img.height;
      // 计算正方形裁剪边长
      const cropSide = Math.min(originW, originH);
      // 计算居中裁剪的起点坐标
      const cropX = (originW - cropSide) / 2;
      const cropY = (originH - cropSide) / 2;
      // 传入完整参数完成绘制
      ctx.drawImage(
        img,
        cropX, cropY, cropSide, cropSide,
        targetX, targetY, CELL_SIZE, CELL_SIZE
      );
    };
    img.src = 'https://source.unsplash.com/random';
  }
}

扩展调整

如果需要修改裁剪位置(比如竖图优先保留顶部内容、横图优先保留左侧内容),只需要调整cropX或cropY的计算值即可:

  • 竖图裁顶部:cropY = 0
  • 横图裁左侧:cropX = 0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:54:14