在产品开发中,难免会有图片上传,但昂贵的图片资源服务会造成一大笔费用,图片压缩是图片静态资源优化的一种常用手段,那么前端如何在图片压缩中贡献自己的一份力量,此文是在【商图助理】小程序过程中开发的一款组件,在使用中体验还是不错的,近期在公司项目【活动抽奖】小程序重构过程中我想到了曾经封装的这款组件,进行了少许的优化,以及文档说明并如到【活动抽奖】项目中,下方为该组件的代码,使用uni-app,vue语法封装
html
<view classs="img-compress">
<canvas :style="{width:canvasWidth+'px',height:canvasHeight +'px'}" class="canvas" canvas-id="compressCanvasId"></canvas></view>
js
export default {
name: 'img-compress',
props: {
maxWidth: {
type: Number,
default: 750
},
ql: {
type: Number,
default: 0.4
},
number: {
type: Number,
default: 1
},
size: {
type: Number,
default: 200 //500KB 500*1024B
},
},
data() {
return {
tempFilePathsList:[], //临时图片列表
canvasWidth:10,
canvasHeight:10,
cpImgList:[],//压缩后图片地址
chooseImgLength:0,
timeID:'',
index: 0
};
},
created() {
},
mounted () {
},
methods: {
addImg(){
let _this = this
uni.chooseImage({
count: _this.number, //默认9
sizeType: ['compressed'], //指定是压缩图
sourceType: ['album','camera'], //从相册选择
success: function (res) {
_this.chooseImgLength = res.tempFilePaths.length;
_this.tempFilePathsList = res.tempFilePaths;
_this.cpImg(res.tempFilePaths[_this.index],_this.index+1)//处理第一张
},
fail: function (e) {
// _this._err(e.errMsg)
}
});
},
cpImg(src,i){//压缩图片
let _this = this
uni.showLoading({
title: '图片压缩中'+i+ '/' + _this.chooseImgLength
});
uni.getImageInfo({
src: src,
success: function (image) {
if(image.type.indexOf('gif') == -1){
if(image.width < image.height){//竖图
if(image.width > _this.maxWidth){//宽度过大,等比例缩放
_this.canvasWidth = _this.maxWidth
_this.canvasHeight = _this.maxWidth * image.height /image.width
}else{//没有大于限制,不等比例缩放
_this.canvasWidth = image.width
_this.canvasHeight = image.height
}
}else{//横图
if(image.height > _this.maxWidth){//宽度过大,等比例缩放
_this.canvasHeight = _this.maxWidth
_this.canvasWidth = _this.maxWidth * image.width /image.height
}else{//没有大于限制,不等比例缩放
_this.canvasWidth = image.width
_this.canvasHeight = image.height
}
}
uni.getFileInfo({
filePath: src,
success: function (res) {
if(res.size /1024 > _this.size){//压缩
_this._cpImg(src)
}else{//不压缩直接压入cpImgList
if(_this.index+1 < _this.chooseImgLength){
_this.cpImg(_this.tempFilePathsList[_this.index+1],_this.index+2)
_this.index = _this.index+1;
}
_this.cpImgListAdd(src)
}
},
fail: function (e) {
_this._err(e.errMsg)
}
})
}else{
_this.cpImgListAdd(image.path)
}
},
fail: function (e) {
_this._err(e.errMsg)
}
});
},
_cpImg(img){
let _this = this
console.log(img,_this.canvasWidth,_this.canvasHeight)
const ctx = uni.createCanvasContext('compressCanvasId',this);
ctx.setFillStyle('#FFFFFF');
ctx.fillRect(0, 0, parseInt(_this.canvasWidth),parseInt(_this.canvasHeight));
ctx.save();
ctx.drawImage(img,0,0,parseInt(_this.canvasWidth),parseInt(_this.canvasHeight));
ctx.save();
ctx.draw(false, function(e){
let timeId = setTimeout(()=>{ //防止安卓出现报错 canvasToTempFilePath:fail:create bitmap failed
console.log('画完了')
clearTimeout(timeId)
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: parseInt(_this.canvasWidth),
height: parseInt(_this.canvasHeight),
destWidth: parseInt(_this.canvasWidth),
destHeight: parseInt(_this.canvasHeight),
canvasId: 'compressCanvasId',
fileType: 'jpg',
quality: Number(_this.ql),
success: function(res) {
if(_this.index+1 < _this.chooseImgLength){
_this.cpImg(_this.tempFilePathsList[_this.index+1],_this.index+2)
_this.index = _this.index+1;
}
_this.cpImgListAdd(res.tempFilePath)
},
fail: function(res){
console.log(res)
_this._err(res.errMsg)
}
},_this)
}, 400);
})
},
cpImgListAdd(img){//向压缩图片数组添加
let _this = this
if(_this.cpImgList.length < _this.chooseImgLength){
_this.cpImgList.push(img)
if(_this.cpImgList.length == _this.chooseImgLength){
uni.hideLoading();
_this.$emit('result', _this.cpImgList);
_this.tempFilePathsList=[] //临时图片列表
_this.canvasWidth=0
_this.canvasHeight=0
_this.cpImgList=[]//压缩后图片地址
_this.index = 0
}
}else{ //向父元素抛出压缩数组,并清除缓存的数据
uni.hideLoading();
_this.$emit('result', _this.cpImgList);
_this.tempFilePathsList=[] //临时图片列表
_this.canvasWidth=0
_this.canvasHeight=0
_this.cpImgList=[]//压缩后图片地址
_this.index = 0
}
},
_err(e){
uni.showToast({
title: e
})
}
}
}css
.canvas{//将canvas定位于屏幕外
position: fixed;
z-index: -1;
left: -9999px;
top: -9999px;
}使用方法
# wkiwi-img-compress
uni 图片等比例压缩组件 主要兼容微信小程序
## 背景
小程序自带压缩比例太小,会造成上传图片带宽浪费,前端对图片进行初次压缩
## 实现思路
使用 `uni.createCanvasContext()` 进行canvas绘图压缩图片
## 使用方法
1. 安装组件
```
npm install --save wkiwi-img-compress
```
2. 在页面引入组件 wkiwi-img-compress
```js
import wkiwiImgCompress from "../wkiwi-img-compress/wkiwi-img-compress.vue";
```
3. WXML 文件中引用 wkiwi-img-compress
```html
<img-compress
ref="cpimg"
@result="cpimgOk"
@err="cpimgErr"
:number="imgNumber-insertImgList.length"
:size="200"
:maxWidth="750"
:ql="0.5"
></img-compress>
```
**wkiwi-img-compress 的属性介绍如下:**
| 字段名 | 类型 | 必填 | 描述 |
| -------------------| ------- | ---- | --------------------------------------------- |
| number | Number | 是 | 一次性压缩图片数量 |
| size | Number | 否 | 文件大小超过限制压缩KB |
| maxWidth | Number | 否 | 限制图片最大边宽度 |
| ql | Number | 否 | 压缩比率 0~1 值越小图片压缩比越大 |
4. 组件压缩图片结果抛出
```js
cpimgOk: function (tempFilePaths){//压缩后图片的零时地址数组
console.log(tempFilePaths)
},
cpimgErr: function (tempFilePaths){//压缩过程中异常抛出
console.log(tempFilePaths)
},
```

