Javascript旋转canvas出现拉伸问题 仅2:1宽高比显示正常如何解决
问题产生原因
- Canvas存在两套独立的尺寸体系:
- 绘图缓冲区尺寸:由
<canvas>元素自带的width、height属性控制,默认值为300px * 150px,宽高比固定为2:1,决定了绘图的像素坐标空间 - 页面显示尺寸:由CSS规则的
width、height属性控制,仅决定canvas元素在页面中的展示大小
- 绘图缓冲区尺寸:由
- 你没有显式设置canvas的
width、height属性,使用了默认2:1的缓冲区比例。当CSS设置的显示比例刚好为2:1时,缓冲区内容会等比缩放适配显示尺寸,所以显示正常;其余比例下,缓冲区内容会被强制拉伸适配显示尺寸,因此出现变形。
优化实现方案
1. 解决拉伸问题
首先对齐canvas的绘图缓冲区尺寸和显示尺寸比例,推荐直接将缓冲区尺寸设置为和显示尺寸完全一致,从根源避免拉伸:
const canvas = document.getElementById('canvas'); // 显式设置绘图缓冲区尺寸,和显示尺寸匹配 canvas.width = 400; canvas.height = 400; // 设置页面显示尺寸,也可以直接写在CSS文件中 canvas.style.width = '400px'; canvas.style.height = '400px'; canvas.style.border = '2px solid black';
2. 简化旋转动画逻辑
常规的“绕固定点旋转图形”不需要手动计算相对坐标和角度,按照平移坐标系到目标点 -> 旋转坐标系 -> 绘制中心在原点的图形的顺序调用变换接口即可,逻辑更简洁不易出错:
const ctx = canvas.getContext('2d'); const w = canvas.width / 4; const h = canvas.width / 4; let relativeAngle = 0; // 固定旋转中心为canvas正中间 const targetX = canvas.width / 2; const targetY = canvas.height / 2; ctx.fillStyle = 'red'; function draw() { relativeAngle += 3; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); // 先将坐标系原点平移到目标旋转中心 ctx.translate(targetX, targetY); // 绕当前原点旋转 ctx.rotate(relativeAngle * Math.PI / 180); // 绘制中心和原点重合的矩形 ctx.fillRect(-w / 2, -h / 2, w, h); ctx.restore(); requestAnimationFrame(draw); } draw();
该方案适配任意canvas宽高比,只要提前对齐缓冲区和显示尺寸比例,就不会出现拉伸问题。
内容的提问来源于stack exchange,提问作者Stephen Witwick
相关产品推荐
相关产品推荐

