Canvas转图片后显示不一致,文本内容异常问题排查
你遇到的问题我get到了——原Canvas里的文本是带波浪扭曲效果的,但转成PNG图片后却变成了平直的普通文本,和预期完全不符对吧?结合你贴的两段代码,我帮你梳理下几个最可能的原因:
可能的问题根源
画布尺寸属性与CSS显示不匹配
看你的转换代码,是直接取myconvas这个画布的toDataURL,但很多人容易忽略一个点:Canvas的原生width/height属性和CSS设置的宽高是两回事。比如如果你的画布属性设的是width:300;height:150,但CSS给它设成了width:600px;height:300px,页面上看到的是缩放后的扭曲效果,但toDataURL捕获的是画布原生分辨率的内容——也就是未缩放的原始文本,自然和页面显示不一样。绘制流程的同步问题
你的Canvas生成逻辑是先在离屏画布@os上用fillText画原始文本,再通过逐列drawImage用正弦曲线扭曲到主画布。如果这段绘制代码是在动画循环(比如requestAnimationFrame)里执行的,或者有异步逻辑,那你调用toDataURL的时候,可能主画布的扭曲绘制还没完成,就只捕获了还没被扭曲的原始文本。上下文配置不一致
检查下离屏画布的上下文@octx和主画布的@ctx,两者的字体、填充颜色、文本对齐方式、抗锯齿设置这些有没有保持一致?比如如果@octx用的是16px字体,主画布却用了24px,那绘制出来的内容肯定会有差异,转成图片后自然不对。
针对性解决建议
对齐画布的属性与CSS尺寸
打开开发者工具检查myconvas的属性,确保它的width和height属性值和CSS设置的宽高完全一致。比如页面上要显示600x300的画布,就直接在HTML里写<canvas id="myconvas" width="600" height="300"></canvas>,不要靠CSS缩放来调整大小。确保绘制完成后再执行转换
如果你的扭曲绘制是在动画帧里,那把转换代码放在绘制完成的回调里,或者用setTimeout延迟个几十毫秒再调用toDataURL,保证主画布的扭曲效果已经完全渲染好了再捕获。比如:// 假设你的绘制函数叫drawTextCurve drawTextCurve(); setTimeout(() => { const tmp_canvas = document.getElementById('myconvas'); const dataURL = tmp_canvas.toDataURL("image/png"); $('#PL01_fo').append($('<img/>', { src : dataURL })); }, 50);统一上下文配置
在调用fillText之前,给离屏画布的上下文@octx设置好和主画布一致的样式,比如:@octx.font = @ctx.font; // 和主画布用一样的字体 @octx.fillStyle = @ctx.fillStyle; @octx.textAlign = "center"; // 对应你代码里的@w*0.5居中绘制 @octx.textBaseline = "middle";验证主画布的实时内容
转换前可以先把主画布临时显示在页面上,确认它的显示效果和你预期的扭曲文本一致,再调用toDataURL,避免转错了画布(比如不小心转了离屏画布而不是主画布)。
内容的提问来源于stack exchange,提问作者Ali Kazmi

