h5图片压缩

/**
 * Created Date: 2018-06-21
 * Author: 于家成
 
 * Last Modified: Fri Jun 29 2018
 * Modified By: 于家成
 
 * Copyright (c) 2018
 * ------------------------------------
 * Javascript will save your soul!
 */

;(function (global, factory) {
    // console.log(module);
    if (typeof module !== "undefined" && module.exports) {
        module.exports = factory();
    } else if (typeof define === "function" && define.amd) {
        define(factory);
    } else {
        global.PictureCompress = factory();
    }
}(this, (function () {
    "use strict"

    var DEFAULTS = {
        quality: 0.1, //设置图片的压缩质量
        maxsize: 100 * 1024, //图片大小
        maxRatio: 4000000, //最大像素
        maxUploadfiles: 9, //同时允许上传的照片数量
        tmpId: null, //input生成的位置
        inputId: null, //
        showBox: null, //图片预览的容器
    };

    // RegExps
    var REGEXP_IMG_FORMAT = /\/(?:jpeg|png|gif)/i;
    // var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g;
    // var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i;
    // var REGEXP_SPACES = /\s+/;
    // var REGEXP_SUFFIX = /^(width|height|left|top|marginLeft|marginTop)$/;
    // var REGEXP_TRIM = /^\s+(.*)\s+$/;
    // var REGEXP_USERAGENT = /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i;
    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
        return typeof obj;
    } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    };
    //tools
    function isObject(obj) {
        return (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj !== null;
    }

    function extend(obj) {
        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            args[_key - 1] = arguments[_key];
        }

        if (isObject(obj) && args.length > 0) {
            if (Object.assign) {
                return Object.assign.apply(Object, [obj].concat(args));
            }

            args.forEach(function (arg) {
                if (isObject(arg)) {
                    Object.keys(arg).forEach(function (key) {
                        obj[key] = arg[key];
                    });
                }
            });
        }
        return obj;
    }

    function PictureCompress(files, opt) {
        if (this instanceof PictureCompress) {
            this._init(opt);
        } else {
            return new PictureCompress(files, opt);
        }
    }
    PictureCompress.prototype = {
        constructor: this,
        _init: function (opt) {
            var self = this;
            this.opt = extend(DEFAULTS, opt);
            this.dom = this._parseToDom();
            this.dom.onchange = function (e) {
                self._change.apply(self, this.files);
            }
        },
        _parseToDom: function () {
            var div = document.getElementById(this.opt.tmpId);
            var input = document.createElement('input');
            input.type = "file";
            input.accept = "image/*";
            input.multiple = true;
            input.id = this.opt.inputId;
            input.style.display = "none";
            div.appendChild(input)
            return input;
        },
        _change: function () {
            var self = this;
            if (!arguments.length) return;
            var files = Array.prototype.slice.call(arguments);
            if (files.length > this.opt.maxUploadfiles) {
                alert("最多同时只能上传" + this.opt.maxUploadfiles + "张图片")
                return;
            }

            files.forEach(function (file, i) {
                if (!REGEXP_IMG_FORMAT.test(file.type)) return;
                var reader = new FileReader();
                var li = document.createElement("li");
                var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) +
                    "KB";
                li.innerHTML = '<div class="progress"><span></span></div><div class="size">' + size + '</div>';
                document.querySelector("#" + self.opt.showBox).appendChild(li);
                reader.readAsDataURL(file);
                reader.onload = function () {
                    var result = this.result;
                    var img = new Image();
                    img.src = result;
                    li.style.background = "url(" + result + ")";
                    //如果图片大小小于100kb,则直接上传
                    if (result.length <= self.opt.maxsize) {
                        img = null;
                        // upload(result, file.type, $(li));
                        return;
                    }
                    //      图片加载完毕之后进行压缩,然后上传
                    if (img.complete) {
                        callback();
                    } else {
                        img.onload = callback;
                    }

                    function callback() {
                        var data = self._compress(img);
                        // upload(data, file.type, $(li));
                        img = null;
                    }
                };
            })
        },
        _compress: function (img) {
            var self = this;
            var initSize = img.src.length,
                width = img.width,
                height = img.height,
                ratio, //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
                count;

            if ((ratio = width * height / self.opt.maxRatio) > 1) {
                ratio = Math.sqrt(ratio);
                width /= ratio;
                height /= ratio;
            } else {
                ratio = 1;
            }
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext('2d');
            //   瓦片canvas
            var tCanvas = document.createElement("canvas");
            var tctx = tCanvas.getContext("2d");
            canvas.width = width;
            canvas.height = height;

            ctx.fillStyle = "#fff";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            //如果图片像素大于100万则使用瓦片绘制
            if ((count = width * height / 1000000) > 1) {
                count = Math.sqrt(count) % 1 > 1 ? ~~(Math.sqrt(count) + 1) : ~~(Math.sqrt(count)); //计算要分成多少块瓦片
                //            计算每块瓦片的宽和高
                var nw = ~~(width / count);
                var nh = ~~(height / count);
                tCanvas.width = nw;
                tCanvas.height = nh;
                for (var i = 0; i < count; i++) {
                    for (var j = 0; j < count; j++) {
                        tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                        ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
                    }
                }
            } else {
                ctx.drawImage(img, 0, 0, width, height);
            }
            //进行最小压缩
            var ndata = canvas.toDataURL('image/jpeg', self.opt.quality);
            console.log('压缩前:' + initSize);
            console.log('压缩后:' + ndata.length);
            console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
            tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
            return ndata;
        }
    }
    return PictureCompress;
})))

使用方式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #chooise{
            height: 300px;
            width: 300px;
            line-height: 300px;
            text-align: center;
            font-size: 20px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <ul id="zhanshi">
        <!--  预览展示box -->
    </lu>
    <div id="showbox">
        <div id="chooise">
            选择图片
        </div>
    </div>

    <script src="compress.js"></script>
    <script>
        PictureCompress(null,{
            tmpId:"showbox",  //input插入位置
            inputId:"upBtn",  //规定插入的input id
            showBox:"zhanshi"   //  用于预览展示的box
        })
        document.querySelector("#chooise").addEventListener("click",function(e){
            document.querySelector("#upBtn").click();
        },false)
       
    </script>
</body>
</html>
封装的不是很完善,有时间再改进可以,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_30346089/article/details/80856011