使用drawImage从Video元素绘图异常,分辨率错乱问题求助
解决Canvas drawImage绘制Video只显示小块/分辨率过低的问题
兄弟,我之前跟你一模一样,折腾这个问题快把头发薅秃了!一开始用this.canvasContext.drawImage(this.mainVideoElement, 0, 0),结果只显示视频左上角一小坨,后来试了drawImage各种参数组合,手动设宽高也没用,画出来的内容分辨率比视频低好几倍。后来才搞清楚是两个核心坑没踩对,给你捋捋解决方案:
1. 先区分Canvas的「真实绘图尺寸」和「CSS显示尺寸」
Canvas有两个完全独立的尺寸:
- 一个是绘图缓冲区的实际像素尺寸(通过
canvas.width/canvas.height控制),这才是决定绘制清晰度的关键; - 另一个是CSS里的显示尺寸,只是控制Canvas在页面上看起来多大,和绘图分辨率无关。
如果只给Canvas设了CSS尺寸,它的绘图缓冲区会默认用300x150的极小尺寸,这就导致你画视频的时候,只能显示左上角一小块,而且内容糊得离谱。
解决办法:
先获取视频的实际分辨率(注意是video.videoWidth和video.videoHeight,不是视频元素的CSS宽高!),然后把Canvas的绘图缓冲区尺寸设成和视频一致:
// 等视频加载完元数据再执行,不然videoWidth/videoHeight会是0 this.mainVideoElement.addEventListener('loadedmetadata', () => { this.canvas.width = this.mainVideoElement.videoWidth; this.canvas.height = this.mainVideoElement.videoHeight; });
如果需要Canvas在页面上按特定大小显示,再单独设置CSS样式,比如:
canvas { width: 800px; /* 你想要的显示宽度 */ height: auto; /* 保持视频比例不变形 */ }
2. 用drawImage的完整参数指定源和目标尺寸
直接用drawImage(video, 0, 0)的时候,Canvas会默认按视频元素的CSS尺寸来绘制,而不是视频的实际分辨率,这就会导致要么只显示一部分,要么拉伸模糊。正确的做法是指定完整的8个参数:
this.canvasContext.drawImage( this.mainVideoElement, 0, 0, this.mainVideoElement.videoWidth, this.mainVideoElement.videoHeight, // 源:取视频实际分辨率 0, 0, this.canvas.width, this.canvas.height // 目标:和Canvas绘图缓冲区尺寸匹配 );
这样就能保证视频的每一个像素都对应到Canvas的像素上,不会出现裁切或模糊。
3. 额外避坑提示
- 一定要等视频触发
loadedmetadata事件再执行绘制,不然videoWidth和videoHeight还没拿到正确值,设置的Canvas尺寸会是0; - 如果视频是动态切换源的,记得每次切换后重新获取视频分辨率并更新Canvas的
width和height; - 要是你的Canvas需要响应窗口大小变化,记得在 resize 事件里重新调整CSS显示尺寸,但别改
canvas.width/canvas.height(不然绘图分辨率会变)。
内容的提问来源于stack exchange,提问作者Shane Duffy
相关产品推荐
相关产品推荐

