/**
* 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>
封装的不是很完善,有时间再改进可以,欢迎指正