Object.create和new Object
new Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。
Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。
// new Object() 方式创建
var a = { rep : 'apple' }
var b = new Object(a)
console.log(b) // {rep: "apple"}
console.log(b.__proto__) // {}
console.log(b.rep) // "apple"
// Object.create() 方式创建
var a = { rep: 'apple' }
var b = Object.create(a)
console.log(b) // {}
console.log(b.__proto__) // {rep: "apple"}
console.log(b.rep) // "apple"
二分查找法压缩图片
methods: {
uploadFile() {
const file = this.$refs.frontRef.files[0];
this.compress(file, 50)
.then(res => {
console.log(res)
})
},
getObjectUrl(file) {
let url = null;
if (window.createObjectURL != undefined) {
// basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
},
fileToImage(blob) {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(img);
img.src = this.getObjectUrl(blob);
});
},
imgToCanvas(img) {
return new Promise((resolve) => {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const imgWidth = img.width;
const imgHeight = img.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// 尺寸与原图保持一致,因此等高等宽
context.clearRect(0, 0, imgWidth, imgHeight);
context.drawImage(img, 0, 0, imgWidth, imgHeight);
resolve(canvas);
});
},
canvasToBlob(canvas, type, encoderOptions){
return new Promise(resolve => {
canvas.toBlob(function(blob){
return resolve(blob);
}, type, encoderOptions);
})
},
compress(originfile, limitedSize) {
return new Promise(async (resolve, reject) => {
const originSize = originfile.size / 1024; // 计算文件大小 单位为kb
// 若小于limitedSize,则不需要压缩,直接返回
if (originSize < limitedSize) {
resolve({ file: originfile, msg: "体积小于期望值,无需压缩!" });
return;
}
// 将获取到的文件恢复成图片
const img = await this.fileToImage(originfile);
// 使用此图片生成需要的canvas
const canvas = await this.imgToCanvas(img);
// 为规避js精度问题,将encoderOptions乘100为整数,初始最大size为MAX_SAFE_INTEGER
const maxQualitySize = {
encoderOptions: 100,
size: Number.MAX_SAFE_INTEGER,
};
// 初始最小size为0
const minQualitySize = { encoderOptions: 0, size: 0 };
let encoderOptions = 100; // 初始质量参数
let count = 0; // 压缩次数
let errorMsg = ""; // 出错信息
let compressBlob = null; // 压缩后的文件Blob
// 压缩思路,用二分法找最佳的压缩点 最多尝试8次即可覆盖全部可能
while (count < 8) {
compressBlob = await this.canvasToBlob(
canvas,
"image/jpeg",
encoderOptions / 100
);
const compressSize = compressBlob.size / 1024;
count++;
if (compressSize === limitedSize) {
// 压缩后的体积与期望值相等 压缩完成,总共压缩了count次
break;
} else if (compressSize > limitedSize) {
// 压缩后的体积比期望值大
maxQualitySize.encoderOptions = encoderOptions;
maxQualitySize.size = compressSize;
} else {
// 压缩后的体积比期望值小
minQualitySize.encoderOptions = encoderOptions;
minQualitySize.size = compressSize;
}
encoderOptions = (maxQualitySize.encoderOptions + minQualitySize.encoderOptions) >> 1;
if (maxQualitySize.encoderOptions - minQualitySize.encoderOptions < 2) {
if (!minQualitySize.size && encoderOptions) {
encoderOptions = minQualitySize.encoderOptions;
} else if (!minQualitySize.size && !encoderOptions) {
errorMsg = "压缩失败,无法压缩到指定大小";
break;
} else if (minQualitySize.size > limitedSize) {
errorMsg = "压缩失败,无法压缩到指定大小";
break;
} else {
// 压缩完成
encoderOptions = minQualitySize.encoderOptions;
compressBlob = await this.canvasToBlob(
canvas,
"image/jpeg",
encoderOptions / 100
);
break;
}
}
}
// 压缩失败,则返回原始图片的信息
if (errorMsg) {
reject({
msg: errorMsg,
file: originfile,
});
return;
}
const compressSize = compressBlob.size / 1024;
console.log(`最后一次压缩后,encoderOptions为:${encoderOptions},大小:${compressSize}`);
// 生成文件
const compressedFile = new File([compressBlob], originfile.name, {type: "image/jpeg"});
resolve({ file: compressedFile, compressBlob, msg: "压缩成功!" });
});
},
},