修身养性,知行合一

  • 首页
  • 爱码
    • 系统
    • 数据库
    • JavaScript
    • CSharp
    • Python
  • 生活
    • 文化
    • 美食
  • 杂谈
  • 关于
修身养性,知行合一
码字,杂谈
  1. 首页
  2. 爱码
  3. 前端
  4. JavaScript
  5. 正文

JavaScript异步加载图片

2019年11月7日 3214点热度 0人点赞 0条评论

之前写的画板里面,我将它升级了一下,首先可以传入一张默认图片,然后所有操作都是基于该图片进行操作。然后我发现,当使用橡皮擦的时候,它直接将整个canvas擦成了透明。

这是因为canvas每次只能展示一张图片,这个在之前说过,有兴趣的朋友可以参考之前的文章。

于是有了很简单的想法,在擦除完成后,首先在canvas中加载原始图片,然后加载擦除后的图片,这样重叠合并成一张完整的擦除后的效果图。

有了想法,动手做:

// 首先保存擦除的图片
let eraserPic = new Image();
eraserPic.src = this.canvasElem.toDataURL("image/png");

// 加载原始图片
let originPic = new Image();
originPic.src = this.originImage;

// 对原始图片响应,这里需要使用`load`响应,否则会有神奇的效果。。。
originPic.addEventListener("load", () => {
    this.ctx.drawImage(originPic, 0, 0, this.canvasElem.width, this.canvasElem.height);

    // 先加载原始图,然后加载擦除后的图片,这样原始图片在下,擦除图片在上面,进行合并
    eraserPic.addEventListener("load", () => {
        this.ctx.drawImage(eraserPic, 0, 0, this.canvasElem.width, this.canvasElem.height);

        // 保存合并后的图片
        this.capturePic = this.canvasElem.toDataURL("image/png");

        // 将新图片添加到undo区域,方便后续操作
        this.undoPushHandle();
    });
});

然后发现真实可用,但是发现总会有问题,时不常一擦除就清空,只显示原始图。多次检查后,感觉是load事件的加载问题,图片加载是一个等待过程,但是我们的代码操作的很快,这样就会出现没有监听到,代码认为不需要load,也就不会加载load里面的事件。

一开始我把所有addEventListener都写在了一层,发现问题后,套了进去,还是有小概率机会出现不加载的问题,于是想到了Promise。

使用异步加载图片

异步的内容很简单,封装一个新建Image的函数,让所有图片都加载好之后返回即可。这样就可以完全等待图片加载成功后执行下一步。

newImageProcess: function(src) {
    return new Promise((resolve, reject) => {
        let img = new Image();
        // 因为有些地方获取图片需要使用跨域截图,所有添加到这里
        img.setAttribute("crossOrigin", "anonymous");
        img.onload = () => resolve(img);
        img.onerror = reject;
        // src赋值在最后,这样做更加保险可以调用`load`事件。
        img.src = src;
    })
}

有了这段代码,后面的操作就行云流水般的简单明了了。

this.newImageProcess(this.canvasElem.toDataURL("image/png")).then((result) => {
    // 首先加载擦除后的图片,保存为变量
    let eraserPic = result;

    this.newImageProcess(this.originImage).then((result) => {
        // 然后加载原始图片,同样保存为变量
        let originPic = result;

        // 依次在canvas中加载原始图片和擦除后图片,使其合并为一张最终效果图
        this.ctx.drawImage(originPic, 0, 0, this.canvasElem.width, this.canvasElem.height);
        this.ctx.drawImage(eraserPic, 0, 0, this.canvasElem.width, this.canvasElem.height);

        // 保存图片并添加到undo操作区域
        this.videoCapture = this.canvasElem.toDataURL("image/png");
        this.undoPushHandle();
    }).catch((err) => {
        console.log("origin error");
    });
}).catch((err) => {
    console.log("eraser error");
});

就这样,不仅代码简单很多,而且整洁干净,思路也清晰了很多。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: canvas JavaScript 异步
最后更新:2019年11月7日

jeremyjone

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

取消回复

文章目录
  • 使用异步加载图片
最新 热点 随机
最新 热点 随机
volar 检查 element 表格的 slot-scope 错误 关于 *.vue 文件中使用 TypeScript 声明类型报错的解决方案 element table 加载时宽度闪烁问题 windows 无法登录便签、OneNote等应用 vue2 中 vuex 对 ts 的支持 封装一个极简的右键菜单
volar 检查 element 表格的 slot-scope 错误
LINQ 语句中格式化日期 Terminal中git log不显示中文问题的解决方案 Navicat 12 安装与破解 歌曲分享--爱得太迟 JS 中字符串 replace 的高级用法 美化PowerShell(含WindowsTerminal和VSCode终端)

(っ•̀ω•́)っ✎⁾⁾ 开心每一天

COPYRIGHT © 2021 jeremyjone.com. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

京ICP备19012859号-1

京公网安备 11010802028585号