如何在同一函数中使用双Canvas?二次图片裁剪失效问题
解决两次Canvas裁剪仅第一个生效的问题
问题根源
- 异步执行顺序错误:第一个Canvas的绘制逻辑在
Skin.onload异步回调里,但你在回调外部直接调用canvas.toDataURL(),此时画布还没完成绘制,拿到的是空白画布的DataURL,后续生成的FACE图片自然也是空白的。 - 图片加载未等待:就算拿到了正确的DataURL,
FACE图片的加载是异步过程,直接调用drawImage时图片还没加载完成,同样无法绘制内容。
修正方案
方案1:直接复用第一个Canvas的内容(更高效)
不用转DataURL,直接把第一个Canvas作为第二个Canvas的绘制源,避免异步加载的问题:
let skinin = document.getElementById("skin"); skinin.addEventListener("change", handleFiles); function handleFiles(e) { const canvas = document.getElementById("canvas"); canvas.width = 64; canvas.height = 64; const ctx = canvas.getContext('2d'); const Skin = new Image(); Skin.src = URL.createObjectURL(e.target.files[0]); Skin.onload = function () { // 完成第一个Canvas的裁剪绘制 ctx.drawImage(Skin, -8, -9, canvas.width, canvas.height); console.log(canvas.toDataURL()); // 直接用第一个Canvas作为源,完成第二个Canvas的裁剪 const canvasface = document.getElementById("canvasFACE"); canvasface.width = 64; canvasface.height = 64; const ctxface = canvasface.getContext('2d'); // 注意drawImage参数顺序:源图像、裁剪起始坐标、裁剪宽高、画布绘制坐标、画布绘制宽高 ctxface.drawImage(canvas, 57, 57, 7, 7, 0, 0, canvasface.width, canvasface.height); } }
方案2:等待FACE图片加载完成再绘制(保留DataURL流程)
如果必须通过DataURL中转图片,要给FACE添加onload回调,等待加载完成后再执行绘制:
let skinin = document.getElementById("skin"); skinin.addEventListener("change", handleFiles); function handleFiles(e) { const canvas = document.getElementById("canvas"); canvas.width = 64; canvas.height = 64; const ctx = canvas.getContext('2d'); const Skin = new Image(); Skin.src = URL.createObjectURL(e.target.files[0]); Skin.onload = function () { ctx.drawImage(Skin, -8, -9, canvas.width, canvas.height); const face = canvas.toDataURL(); const FACE = new Image(); // 等待FACE加载完成后再绘制第二个Canvas FACE.onload = function() { const canvasface = document.getElementById("canvasFACE"); canvasface.width = 64; canvasface.height = 64; const ctxface = canvasface.getContext('2d'); ctxface.drawImage(FACE, 57, 57, 7, 7, 0, 0, canvasface.width, canvasface.height); } FACE.src = face; } }
额外注意
drawImage的完整参数是:ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
sx/sy:源图像的裁剪起始坐标sWidth/sHeight:源图像裁剪的宽高(第一个Canvas仅64x64,从(57,57)开始最多只能裁剪7x7的区域)dx/dy:画布上的绘制起始坐标dWidth/dHeight:画布上的绘制宽高
你原代码的参数会导致裁剪区域超出第一个Canvas的范围,需根据实际需求调整数值。
内容的提问来源于stack exchange,提问作者Yahia
相关产品推荐
相关产品推荐

