332 lines
9.6 KiB
Vue
332 lines
9.6 KiB
Vue
|
<template xlang="wxml" minapp="mpvue">
|
|||
|
<view class="_imageCompress">
|
|||
|
<canvas id="_myCanvas" canvas-id="_myCanvas" :style="{width:cWidth+'px',height:cHeight+'px'}" />
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
let _rtArr = [], _cgFile = '', _index = 0;
|
|||
|
export default {
|
|||
|
name: "imageCompress",
|
|||
|
props: {
|
|||
|
maxWidth: {
|
|||
|
type: Number,
|
|||
|
default: 750
|
|||
|
},
|
|||
|
type: {
|
|||
|
type: String,
|
|||
|
default: 'url'
|
|||
|
},
|
|||
|
ql: {
|
|||
|
type: Number,
|
|||
|
default: 0.92
|
|||
|
},
|
|||
|
src: {
|
|||
|
type: String,
|
|||
|
default: ''
|
|||
|
},
|
|||
|
number: {
|
|||
|
type: Number,
|
|||
|
default: 1
|
|||
|
},
|
|||
|
fixOrientation: {
|
|||
|
type: Boolean,
|
|||
|
default: true
|
|||
|
},
|
|||
|
size: {
|
|||
|
type: Number,
|
|||
|
default: 500000
|
|||
|
},
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
cWidth: 750,
|
|||
|
cHeight: 750,
|
|||
|
}
|
|||
|
},
|
|||
|
onUnload: function () {
|
|||
|
},
|
|||
|
methods: {
|
|||
|
// 选择照片
|
|||
|
_changImg() {
|
|||
|
let that = this;
|
|||
|
if (that.src == '') {
|
|||
|
uni.chooseImage({
|
|||
|
count: that.number, //默认9
|
|||
|
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
|
|||
|
// sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
|||
|
success: function (res) {
|
|||
|
_rtArr = [];
|
|||
|
_cgFile = res.tempFilePaths;
|
|||
|
_index = 0;
|
|||
|
that._imageCompress()
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
that._err(e)
|
|||
|
// console.log(JSON.stringify(res.tempFilePaths));
|
|||
|
}
|
|||
|
});
|
|||
|
} else {
|
|||
|
_imageCompress(that.src)
|
|||
|
}
|
|||
|
},
|
|||
|
// 压缩图片
|
|||
|
_imageCompress() {
|
|||
|
let that = this, resPath = _cgFile[_index];
|
|||
|
// #ifdef APP-PLUS
|
|||
|
uni.hideLoading();
|
|||
|
// #endif
|
|||
|
uni.showLoading({
|
|||
|
title: `图片压缩中 ${_index + 1}/${_cgFile.length}`,
|
|||
|
mask: true
|
|||
|
});
|
|||
|
// 获取图片信息
|
|||
|
// #ifndef H5
|
|||
|
uni.getImageInfo({
|
|||
|
src: resPath,
|
|||
|
success: function (image) {
|
|||
|
// 如果图片的大小大于设定值才压缩
|
|||
|
uni.getFileInfo({
|
|||
|
filePath: resPath,
|
|||
|
success: function (res) {
|
|||
|
_imageCompress(image, res.size)
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
that._err(e)
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
that._err(e)
|
|||
|
}
|
|||
|
});
|
|||
|
// #endif
|
|||
|
// #ifdef H5
|
|||
|
that._getH5ImageInfo(resPath, d => {
|
|||
|
_imageCompress(d, d.size)
|
|||
|
})
|
|||
|
// #endif
|
|||
|
// 处理图片
|
|||
|
function _imageCompress(image, size) {
|
|||
|
// #ifndef APP-PLUS
|
|||
|
if (image.type.indexOf('png') >= 0) {
|
|||
|
that._result(resPath)
|
|||
|
return false
|
|||
|
}
|
|||
|
// #endif
|
|||
|
let oW = image.width, oH = image.height, scaleWidth = 1, scaleHeight = 1, ctxWidth, ctxHeight;
|
|||
|
if (size / 1024 >= that.size || image.width >= that.maxWidth) {
|
|||
|
// 控制上传图片的宽高
|
|||
|
if (image.width >= image.height && image.width >= that.maxWidth) {
|
|||
|
image.height = that.maxWidth * image.height / image.width;
|
|||
|
image.width = that.maxWidth;
|
|||
|
} else if (image.width < image.height && image.height >= that.maxWidth) {
|
|||
|
image.width = that.maxWidth * image.width / image.height;
|
|||
|
image.height = that.maxWidth;
|
|||
|
}
|
|||
|
scaleWidth = image.width / oW
|
|||
|
scaleHeight = image.height / oH
|
|||
|
}
|
|||
|
ctxWidth = oW * scaleWidth
|
|||
|
ctxHeight = oH * scaleHeight
|
|||
|
const ctx = uni.createCanvasContext('_myCanvas', that);
|
|||
|
that.cWidth = image.width;
|
|||
|
that.cHeight = image.height;
|
|||
|
// 图片旋转修正,只有H5有效
|
|||
|
if (that.fixOrientation) {
|
|||
|
// 旋转图片
|
|||
|
let ot = image.orientation
|
|||
|
if ([5, 6, 7, 8, 'right', 'left', 'right-mirrored', 'left-mirrored'].indexOf(ot) > -1) {
|
|||
|
that.cWidth = image.height;
|
|||
|
that.cHeight = image.width;
|
|||
|
}
|
|||
|
// 代码参考 https://stackoverflow.com/questions/19463126/how-to-draw-photo-with-correct-orientation-in-canvas-after-capture-photo-by-usin
|
|||
|
if (ot == 2 || ot == "up-mirrored") {
|
|||
|
ctx.translate(ctxWidth, 0);
|
|||
|
ctx.scale(-1, 1);
|
|||
|
} else if (ot == 3 || ot == "down") {
|
|||
|
ctx.translate(ctxWidth, ctxHeight);
|
|||
|
ctx.rotate(Math.PI);
|
|||
|
} else if (ot == 4 || ot == "down-mirrored") {
|
|||
|
ctx.translate(0, ctxHeight);
|
|||
|
ctx.scale(1, -1);
|
|||
|
} else if (ot == 5 || ot == "right-mirrored") {
|
|||
|
ctx.rotate(0.5 * Math.PI);
|
|||
|
ctx.scale(1, -1);
|
|||
|
} else if (ot == 6 || ot == "right") {
|
|||
|
ctx.rotate(0.5 * Math.PI);
|
|||
|
ctx.translate(0, -ctxHeight);
|
|||
|
} else if (ot == 7 || ot == "left-mirrored") {
|
|||
|
ctx.rotate(0.5 * Math.PI);
|
|||
|
ctx.translate(ctxWidth, -ctxHeight);
|
|||
|
ctx.scale(-1, 1);
|
|||
|
} else if (ot == 8 || ot == "left") {
|
|||
|
ctx.rotate(-0.5 * Math.PI);
|
|||
|
ctx.translate(-ctxWidth, 0);
|
|||
|
} else {
|
|||
|
ctx.translate(0, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
let ctxTime = 0;
|
|||
|
// #ifndef H5
|
|||
|
ctxTime = 10;
|
|||
|
// #endif
|
|||
|
// #ifdef H5
|
|||
|
ctxTime = cTime();
|
|||
|
// #endif
|
|||
|
setTimeout(() => {
|
|||
|
ctx.drawImage(resPath, 0, 0, ctxWidth, ctxHeight)
|
|||
|
ctx.draw(false, () => {
|
|||
|
let time = 0;
|
|||
|
// #ifndef MP-WEIXIN
|
|||
|
time = 10;
|
|||
|
// #endif
|
|||
|
// #ifdef MP-WEIXIN
|
|||
|
time = cTime();
|
|||
|
// #endif
|
|||
|
setTimeout(() => {
|
|||
|
uni.canvasToTempFilePath({
|
|||
|
width: Number(that.cWidth),
|
|||
|
height: Number(that.cHeight),
|
|||
|
destWidth: Number(that.cWidth),
|
|||
|
destHeight: Number(that.cHeight),
|
|||
|
canvasId: '_myCanvas',
|
|||
|
fileType: 'jpg',
|
|||
|
quality: Number(that.ql),
|
|||
|
success: function (res) {
|
|||
|
if (that.type == 'base64') {
|
|||
|
let img = '';
|
|||
|
//#ifdef MP-WEIXIN
|
|||
|
img = 'data:image/jpeg;base64,' + wx.getFileSystemManager().readFileSync(res.tempFilePath, "base64")
|
|||
|
that._result(img)
|
|||
|
//#endif
|
|||
|
//#ifdef APP-PLUS
|
|||
|
// console.log(JSON.stringify(res))
|
|||
|
plus.io.resolveLocalFileSystemURL(res.tempFilePath, function (entry) {
|
|||
|
entry.file(function (file) {
|
|||
|
let fileReader = new plus.io.FileReader();
|
|||
|
// console.log("getFile:" + JSON.stringify(file));
|
|||
|
fileReader.readAsDataURL(file);
|
|||
|
fileReader.onloadend = function (evt) {
|
|||
|
// console.log(JSON.stringify(evt))
|
|||
|
if (evt.target.readyState == 2) {
|
|||
|
that._result(evt.target.result)
|
|||
|
} else {
|
|||
|
that._err(evt)
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
}, function (e) {
|
|||
|
that._err(e)
|
|||
|
});
|
|||
|
//#endif
|
|||
|
//#ifdef H5
|
|||
|
that._result(res.tempFilePath)
|
|||
|
//#endif
|
|||
|
} else {
|
|||
|
that._result(res.tempFilePath)
|
|||
|
}
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
that._err(e)
|
|||
|
}
|
|||
|
}, that)
|
|||
|
|
|||
|
}, time);
|
|||
|
});
|
|||
|
}, ctxTime);
|
|||
|
function cTime() {
|
|||
|
let time = that.maxWidth / 5
|
|||
|
if (time >= 600) {
|
|||
|
return 600
|
|||
|
} else if (time <= 100) {
|
|||
|
return 100
|
|||
|
} else {
|
|||
|
return time
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
// ios翻转图片
|
|||
|
_reverseImgData(res) {
|
|||
|
let w = res.width
|
|||
|
let h = res.height
|
|||
|
let con = 0
|
|||
|
for (let i = 0; i < h / 2; i++) {
|
|||
|
for (let j = 0; j < w * 4; j++) {
|
|||
|
con = res.data[i * w * 4 + j]
|
|||
|
res.data[i * w * 4 + j] = res.data[(h - i - 1) * w * 4 + j]
|
|||
|
res.data[(h - i - 1) * w * 4 + j] = con
|
|||
|
}
|
|||
|
}
|
|||
|
return res
|
|||
|
},
|
|||
|
_getH5ImageInfo(url, callback) {
|
|||
|
let image = new Image()
|
|||
|
image.src = url
|
|||
|
image.onload = function (d) {
|
|||
|
let imgSelf = this
|
|||
|
let http = new XMLHttpRequest();
|
|||
|
http.open("GET", url, true);
|
|||
|
http.responseType = "blob";
|
|||
|
http.onload = function (e) {
|
|||
|
let httpSelf = this
|
|||
|
if (httpSelf.status == 200 || httpSelf.status === 0) {
|
|||
|
let reader = new FileReader();
|
|||
|
reader.onload = function (e) {
|
|||
|
// 代码参考 https://www.jianshu.com/p/eb855b580780
|
|||
|
let view = new DataView(this.result);
|
|||
|
if (view.getUint16(0, false) != 0xFFD8) return callback({ size: httpSelf.response.size, type: httpSelf.response.type, width: imgSelf.width, height: imgSelf.height, orientation: -1 });
|
|||
|
let length = view.byteLength, offset = 2;
|
|||
|
while (offset < length) {
|
|||
|
let marker = view.getUint16(offset, false);
|
|||
|
offset += 2;
|
|||
|
if (marker == 0xFFE1) {
|
|||
|
if (view.getUint32(offset += 2, false) != 0x45786966) return callback({ size: httpSelf.response.size, type: httpSelf.response.type, width: imgSelf.width, height: imgSelf.height, orientation: -1 });
|
|||
|
let little = view.getUint16(offset += 6, false) == 0x4949;
|
|||
|
offset += view.getUint32(offset + 4, little);
|
|||
|
let tags = view.getUint16(offset, little);
|
|||
|
offset += 2;
|
|||
|
for (let i = 0; i < tags; i++)
|
|||
|
if (view.getUint16(offset + (i * 12), little) == 0x0112)
|
|||
|
return callback({ size: httpSelf.response.size, type: httpSelf.response.type, width: imgSelf.width, height: imgSelf.height, orientation: view.getUint16(offset + (i * 12) + 8, little) });
|
|||
|
}
|
|||
|
else if ((marker & 0xFF00) != 0xFF00) break;
|
|||
|
else offset += view.getUint16(offset, false);
|
|||
|
}
|
|||
|
return callback({ size: httpSelf.response.size, type: httpSelf.response.type, width: imgSelf.width, height: imgSelf.height, orientation: -1 });
|
|||
|
};
|
|||
|
reader.readAsArrayBuffer(httpSelf.response);
|
|||
|
}
|
|||
|
};
|
|||
|
http.send();
|
|||
|
}
|
|||
|
},
|
|||
|
// 返回图片数据
|
|||
|
_result(src, index) {
|
|||
|
_rtArr.push(src)
|
|||
|
_index = _index + 1;
|
|||
|
if (_cgFile.length - 1 >= _index) {
|
|||
|
this._imageCompress()
|
|||
|
} else {
|
|||
|
uni.hideLoading();
|
|||
|
this.$emit("result", _rtArr);
|
|||
|
}
|
|||
|
},
|
|||
|
_err(src) {
|
|||
|
uni.hideLoading();
|
|||
|
this.$emit("err", src);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style>
|
|||
|
._imageCompress {
|
|||
|
position: fixed;
|
|||
|
top: -99999upx;
|
|||
|
left: -99999upx;
|
|||
|
z-index: -99999;
|
|||
|
}
|
|||
|
</style>
|