canvas 生成和合並圖片

先說背景:工做中遇到一個問題,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);
}

合成效果

圖片一:小站logocanvas

cuihuan_title (1)

圖片二:小圖標:
del後端

合成效果:app

下載

原理簡介

主要是經過canvas 獲取多個圖片的base64編碼,以後經過drawImage 函數合併和toDataUrl的方式合成。dom

問題思考

  • 問題一:必須支持canvas,不然還須要後臺統一跑腳本處理。函數

  • 問題二:性能消耗過大。append img 和base64代碼對dom的消耗都挺大,尤爲是在移動端,很容易形成崩潰。解決辦法:設定最大寬度,將圖片等比縮放,這樣子就少了向dom擴展元素這部分的損耗。性能

  • 問題三:base64 在傳輸上性能消耗也挺大,沒有file原生的好。ui

所以:出了必須前端搞定,最好的方式,仍是在後臺跑腳本運行合併。編碼

我的小站原文連接 spa

相關文章
相關標籤/搜索