图片在线压缩

select img to zip!

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         图片在线压缩
// @namespace    ༺黑白༻
// @version      1.6
// @description  select img to zip!
// @author       Paul
// @match        *://www.baidu.com/
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/layer/2.3/layer.js
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';
    ({
        reader: null,
        loadImg: null,
        canvas: null,
        context: null,
        $body: null,
        itemTotalCount:0,
        createCss: function () {
            $(document.head).append('<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/layer/2.3/skin/layer.css"/>');
            GM_addStyle('.zipcontainer{ position:fixed;width:60px;height:35px;line-height:35px;right: 0;font-size: 12px;top: 50%;transform: translateY(-50%);z-index: 1;cursor: pointer;border-radius: .4em;overflow: hidden;background-color: #38f;color:#fff; }\
             .zipcontainer .zipbtn{ display:block; text-align:center;width:100%;height:100%; }\
             .zipcontainer .zipfile{display:block; position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;z-index:-1; }\
             .maxImg{ max-height:100%;max-width:100%; }\
             .cfg_progress{ width:550px;display:block;height: 30px;line-height: 30px;margin-bottom:10px; }\
             .cfg_progress .cfg_progress_label{ width:70px;display:inline-block;float: left; }\
             .cfg_progress .cfg_progress_bar{ width:450px;display:inline-block;margin-left:15px;height: 30px; }\
             .cfg_progress .cfg_progress_bar span{ background-color:#C1E1FC;width:0;height:100%;display:block;text-align:center;}\
             .cfg_imgs{ width:550px;height:300px;overflow-y:auto;margin-top:5px; }\
             .cfg_imgs .img_item{ float:left;width:115px;margin:3px 3px;border:1px solid #ccc;background-color:#dbdbdb; }\
             .cfg_imgs .img_item:nth-child(4n-3){margin-left:7px;}\
             .cfg_imgs .img_item:nth-child(4n){margin-right:7px;}\
             .cfg_imgs .img_item .img{ height:135px;width:115px;vertical-align: middle;display:table-cell; }\
             .cfg_imgs .img_item .img img{max-height:100%;max-width:100%;margin:0 auto;display:block;}\
             .cfg_imgs .img_item .text{ text-align:center;display:block;line-height:25px;background-color:#fff; }');
            return this;
        },
        createBtn: function () {
            var htmlStr = '<div class="zipcontainer"><span class="zipbtn">图片压缩</span><input accept="image/*" type="file" multiple class="zipfile" /></div>';
            this.$container = $(htmlStr).appendTo(this.$body);
            return this;
        },
        createProcessWin: function () {   
            layer.open({
                type: 1,
                area:['610px','auto'],
                title: '脚本定制可联系:[email protected]',
                content: '<div style="margin: 20px;font-size:13px;">\
                            <div class="cfg_progress">\
                                <div class="cfg_progress_label">压缩进度:</div>\
                                <div class="cfg_progress_bar"><span id="itemCount">0%</span></div>\
                            </div>\
                            <div class="cfg_imgs" id="zipImgs"></div>\
                          </div>\
                         ',
                shade: false,
                success: function (layero, index) {
                    this.$itemCount = layero.find('#itemCount');
                    this.$zipImgs = layero.find('#zipImgs');
                    this.$body.off('item_progress').on('item_progress', function (e, cur, total,imgSrc,originSize,afterZipSize) {
                        var progress = Math.round(cur / total * 100);
                        progress = progress + '%';
                        this.$itemCount.css('width', progress).html(progress);
                        this.$zipImgs.append('<div class="img_item"><div class="img"><img src="' + imgSrc + '"  /></div><span class="text">'+this.computeSize(originSize)+' -> '+this.computeSize(afterZipSize)+'</span><a class="text" href="' + imgSrc +'" download="img" >下载</a></div>');
                    }.bind(this));
                }.bind(this),
                end: function () {
                    this.$container.show();   
                }.bind(this)
            })
        },
        computeSize:function(size){
            var prefix='B',cSize=size;
            if(size>1024){
                prefix='KB';
                cSize = Math.ceil(size/1024);
                if(size>1024*1024){
                    prefix='MB'; 
                    cSize = Math.ceil(size/(1024*1024));
                }
            }
            return cSize+prefix;
        },
        initEvent: function () {
            this.$container.children('span:first').on('click', function (e) { var $this = $(this); $this.next().click(); }).end().children('input:first').on('change', this.onChange.bind(this));
            return this;
        }, 
        onReadFile: function (e) {
            this.loadImg.src = e.target.result;
        },
        onImgLoad: function (dfd,originSize,e) {
            // 图片原始尺寸
            var originWidth = this.loadImg.width;
            var originHeight = this.loadImg.height;
            // 最大尺寸限制,可通过国设置宽高来实现图片压缩程度
            var maxWidth = 800,
                maxHeight = 800;
            // 目标尺寸
            var targetWidth = originWidth,
                targetHeight = originHeight;
            // 图片尺寸超过400x400的限制
            //if (originWidth > maxWidth || originHeight > maxHeight) {
            //    if (originWidth / originHeight > maxWidth / maxHeight) {
            //        // 更宽,按照宽度限定尺寸
            //        targetWidth = maxWidth;
            //        targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            //    } else {
            //        targetHeight = maxHeight;
            //        targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            //    }
            //}
            // canvas对图片进行缩放
            this.canvas.width = targetWidth;
            this.canvas.height = targetHeight;
            // 清除画布
            this.context.clearRect(0, 0, targetWidth, targetHeight);
            // 图片压缩
            this.context.drawImage(this.loadImg, 0, 0, targetWidth, targetHeight);
            /*第一个参数是创建的img对象;第二个参数是左上角坐标,后面两个是画布区域宽高*/
            //压缩后的图片base64 url
            /*canvas.toDataURL(mimeType, qualityArgument),mimeType 默认值是'image/jpeg';
             * qualityArgument表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92*/
            /* this.canvas.toBlob(function(){
              console.log(arguments);
            },'image/jpeg',0.80);
            var newUrl = this.canvas.toDataURL('image/jpeg', 0.80);//base64 格式
            //console.log(canvas.toDataURL('image/jpeg', 0.92));
            dfd.resolve(newUrl); */
            var quality=0.75,formart='image/jpeg';
            this.canvas.toBlob(function(blob){
                dfd.resolve(this.canvas.toDataURL(formart, quality),originSize,blob.size);
            }.bind(this),formart,quality);
        },
        onChange: function (e) {
            var i,file,len,filesArray=[],
                files = e.target.files;
            len = files.length;
            if (len <= 0) {
                layer.msg("请选择要压缩的图片!");
            } else {
                for (i = 0; i < len; i++) {
                    file = files[i];
                    if (file.type.indexOf("image") == 0) {
                        filesArray.push(file);
                    } 
                }  
            }
            this.itemTotalCount = filesArray.length;
            if (this.itemTotalCount > 0) {
                this.$container.hide();
                this.createProcessWin();
                setTimeout(this.doFilesQueue.bind(this, filesArray,0), 100);
            }
            e.target.value='';
        },
        doLoad: function (file) {
            var dfd = $.Deferred();
            this.loadImg.onload = this.onImgLoad.bind(this, dfd,file.size);
            this.reader.onload = this.onReadFile.bind(this);
            this.reader.readAsDataURL(file);
            return dfd.promise();
        },
        doFilesQueue: function (filesArray,itemExecCount) {
            if (filesArray.length > 0) {  
                itemExecCount++;
                this.doLoad(filesArray.shift()).done(this.doProcess.bind(this, filesArray, itemExecCount));
            } 
        },
        doProcess: function (filesArray, itemExecCount,imgSrc,originSize,afterZipSize) {
            this.$body.trigger('item_progress', [itemExecCount, this.itemTotalCount, imgSrc,originSize,afterZipSize]);
            setTimeout(this.doFilesQueue.bind(this, filesArray, itemExecCount), 100);
        },
        run: function () {
            this.$body = $('body');
            this.reader = new FileReader();
            this.loadImg = new Image();
            this.canvas = document.createElement('canvas');
            this.context = this.canvas.getContext('2d');
            this.createCss()
                .createBtn()
                .initEvent();
        }
    }).run();
})();