资讯专栏INFORMATION COLUMN

canvas 生成和合并图片

pkwenda / 2490人阅读

摘要:先上代码获取上传和展现的图片。解决办法设定最大宽度,将图片等比缩放,这样子就少了向扩展元素这部分的损耗。因此出了必须前端搞定,最好的方式,还是在后台跑脚本运行合并。

先说背景:工作中遇到一个问题,file组件上传图片,file是可以上传n张图片;但是,后台逻辑历史原因,只能展现一张。因此:考虑到成本,决定在前端将多张图片合并成一张给后端

先上代码
_mergeImage2Canvas:function() {
    // 获取file上传和展现的图片。一般file上传之后,有个小图标展现。
    var imgs = $(".img_files");
    if (!imgs) {
        return false;
    }

    // 创建原始图像
    // 原因:file上传之后,展现往往是个缩略图,无法取到真正大小
    for (var i = 0; i < imgs.length; i++) {
        var fbwImg   = document.createElement("img");
        var fbwImgID = "temp_img_id" + i;
        $("#" + fbwImgID).remove();
        fbwImg.src   = imgs[i].src;
        fbwImg.className     = "temp-img-class";
        // 不显示,仅供调用
        fbwImg.style.display = "none";

        // 临时区域扩展
        $("#temp_section").append(fbwImg);
    }

    // 合并原始图片,生成一个新的base64 图片
    var getOriginImgBase64 = function (oriImgs) {
        if (!oriImgs) {
            return false;
        }
        
        // 获取canvas的宽高
        // 原因:canvas需要首先指定宽高,所以需要提前获取最终的宽高
        var maxWidth = 0;
        var height = 0;
        for (var i = 0; i < oriImgs.length; i++) {
            var img = oriImgs[i];
            if (img.width > maxWidth) {
                maxWidth = img.width;
            }
            height += img.height;
        }

        // 设定canvas
        var canvas    = document.createElement("canvas");
        canvas.width  = maxWidth + 10;
        canvas.height = height + 10;
        var ctx       = canvas.getContext("2d");

        // 留5margin
        var dheight = 5;
        for (var j = 0; j < oriImgs.length; j++) {
            var img     = oriImgs[j];
            var cheight = img.height;
            var cwidth  = img.width;

            // 留5 margin
            ctx.drawImage(img, 5, dheight, cwidth, cheight);

            dheight = dheight + cheight + 5;
        }

        // 生成的base64 放在需要的一个全局变量中。
        fbw_img_data = canvas.toDataURL("image/png");
        
        // 清理
        $(".temp_img_class").remove();
    };

    // 之所以使用timer,考虑到dom树如果没有加载完成,会取到高度有误差
    var imgTimer = null;
    imgTimer = setTimeout(function () {
        getOriginImgBase64($(".temp_img_class"));

        if (imgTimer) {
            clearTimeout(imgTimer);
        }
    }, 300);
}
合成效果

图片一:小站logo

图片二:小图标:

合成效果:

原理简介

主要是通过canvas 获取多个图片的base64编码,之后通过drawImage 函数合并和toDataUrl的方式合成。

问题思考

问题一:必须支持canvas,否则还需要后台统一跑脚本处理。

问题二:性能消耗过大。append img 和base64代码对dom的消耗都挺大,尤其是在移动端,很容易造成崩溃。解决办法:设定最大宽度,将图片等比缩放,这样子就少了向dom扩展元素这部分的损耗。

问题三:base64 在传输上性能消耗也挺大,没有file原生的好。

因此:出了必须前端搞定,最好的方式,还是在后台跑脚本运行合并。

个人小站原文链接

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86251.html

相关文章

  • 使用box-shadow进行画图(性能优化终结者)

    摘要:关于的介绍关于的介绍处理数据并转换为在上边我们拿到了一个一维数组,接下来就是将它处理为更合理的结构。如果计算出来这一块面积就成为了一个问题目前的思路是,将数组转换为二维数组,而不是单纯的在对象中用标识。 最近突然想做一些好玩的东西,找来找去,想到了之前曾经在网上看到过有人用box-shadow画了一副蒙娜丽莎出来 感觉这个挺有意思,正好趁着周末,自己也搞一波 前言 在线地址: 优化前...

    snifes 评论0 收藏0
  • 使用 canvas 实现精灵动画

    摘要:文章首发于个人博客在最近项目中需要实现一个精灵动画,素材方只提供了一个短视频素材,所以在实现精灵动画之前先介绍两个工具来帮助我们更好的实现需求。 文章首发于个人博客:http://heavenru.com 在最近项目中需要实现一个精灵动画,素材方只提供了一个短视频素材,所以在实现精灵动画之前先介绍两个工具来帮助我们更好的实现需求。在这篇文章中,主要是介绍两个命令行工具来实现将一个短视频...

    岳光 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<