如何在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),直接取全图绘制即可
- 横版图片(宽度>高度):纵向从图片顶端(Y=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
相关产品推荐
相关产品推荐

