|
@@ -0,0 +1,175 @@
|
|
|
+<template>
|
|
|
+ <view class="compress">
|
|
|
+ <canvas :style="{ width: canvasSize.width,height: canvasSize.height}" canvas-id="myCanvas"></canvas>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ pic:'',
|
|
|
+ canvasSize: {
|
|
|
+ width: 0,
|
|
|
+ height: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 压缩
|
|
|
+ compress(params) {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ // 等待图片信息
|
|
|
+ let info = await this.getImageInfo(params.src).then(info=>info).catch(err=>err);
|
|
|
+
|
|
|
+ if(!info){
|
|
|
+ reject('获取图片信息异常');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置最大 & 最小 尺寸
|
|
|
+ const maxSize = params.maxSize || 1080;
|
|
|
+ const minSize = params.minSize || 640;
|
|
|
+
|
|
|
+ // 当前图片尺寸
|
|
|
+ let {width,height} = info;
|
|
|
+
|
|
|
+ // 非 H5 平台进行最小尺寸校验
|
|
|
+ // #ifndef H5
|
|
|
+ if(width <= minSize && height <= minSize){
|
|
|
+ resolve(params.src);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // 最大尺寸计算
|
|
|
+ if (width > maxSize || height > maxSize) {
|
|
|
+ if (width > height) {
|
|
|
+ height = Math.floor(height / (width / maxSize));
|
|
|
+ width = maxSize;
|
|
|
+ } else {
|
|
|
+ width = Math.floor(width / (height / maxSize));
|
|
|
+ height = maxSize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置画布尺寸
|
|
|
+ this.$set(this,"canvasSize",{
|
|
|
+ width: `${width}rpx`,
|
|
|
+ height: `${height}rpx`
|
|
|
+ });
|
|
|
+
|
|
|
+ // Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新
|
|
|
+ setTimeout(() => {
|
|
|
+ const ctx = uni.createCanvasContext('myCanvas', this);
|
|
|
+ ctx.clearRect(0,0,width, height)
|
|
|
+ ctx.drawImage(info.path, 0, 0, uni.upx2px(width), uni.upx2px(height));
|
|
|
+ ctx.draw(false, () => {
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ width: uni.upx2px(width),
|
|
|
+ height: uni.upx2px(height),
|
|
|
+ destWidth: width,
|
|
|
+ destHeight: height,
|
|
|
+ canvasId: 'myCanvas',
|
|
|
+ fileType: params.fileType || 'png',
|
|
|
+ quality: params.quality || 0.9,
|
|
|
+ success: (res) => {
|
|
|
+ // 在H5平台下,tempFilePath 为 base64
|
|
|
+ resolve(res.tempFilePath);
|
|
|
+ },
|
|
|
+ fail:(err)=>{
|
|
|
+ reject(null);
|
|
|
+ }
|
|
|
+ },this);
|
|
|
+ });
|
|
|
+ }, 300);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 获取图片信息
|
|
|
+ getImageInfo(src){
|
|
|
+ return new Promise((resolve, reject)=>{
|
|
|
+ uni.getImageInfo({
|
|
|
+ src,
|
|
|
+ success: (info)=> {
|
|
|
+ resolve(info);
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ reject(null);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 批量压缩
|
|
|
+ batchCompress(params){
|
|
|
+ // index:进度,done:成功,fail:失败
|
|
|
+ let [index,done,fail] = [0,0,0];
|
|
|
+ // 压缩完成的路径集合
|
|
|
+ let paths = [];
|
|
|
+ // 批量压缩方法
|
|
|
+ let batch = ()=>{
|
|
|
+ return new Promise((resolve, reject)=>{
|
|
|
+ // 开始
|
|
|
+ let start = async ()=>{
|
|
|
+ params.progress && params.progress({
|
|
|
+ done,
|
|
|
+ fail,
|
|
|
+ count:params.batchSrc.length
|
|
|
+ });
|
|
|
+ // 等待图片压缩方法返回
|
|
|
+ let path = await next();
|
|
|
+ if(path){
|
|
|
+ done++;
|
|
|
+ paths.push(path);
|
|
|
+ }else{
|
|
|
+ fail++;
|
|
|
+ }
|
|
|
+
|
|
|
+ index++;
|
|
|
+ // 压缩完成
|
|
|
+ if(index >= params.batchSrc.length){
|
|
|
+ resolve(true);
|
|
|
+ }else{
|
|
|
+ start();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ start();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 依次调用压缩方法
|
|
|
+ let next = ()=>{
|
|
|
+ return this.compress({
|
|
|
+ src:params.batchSrc[index],
|
|
|
+ maxSize:params.maxSize,
|
|
|
+ fileType:params.fileType,
|
|
|
+ quality:params.quality,
|
|
|
+ minSize:params.minSize
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 全部压缩完成后调用
|
|
|
+ return new Promise(async (resolve, reject)=>{
|
|
|
+ // 批量压缩方法回调
|
|
|
+ let res = await batch();
|
|
|
+ if(res){
|
|
|
+ resolve(paths);
|
|
|
+ }else{
|
|
|
+ reject(null);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .compress{
|
|
|
+ position: fixed;
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ overflow: hidden;
|
|
|
+ top: -99999px;
|
|
|
+ left: 0;
|
|
|
+ }
|
|
|
+</style>
|