&l">
wkiwi的博客

小程序图片压缩组件封装

发布时间:5年前热度: 4028 ℃评论数:

在产品开发中,难免会有图片上传,但昂贵的图片资源服务会造成一大笔费用,图片压缩是图片静态资源优化的一种常用手段,那么前端如何在图片压缩中贡献自己的一份力量,此文是在【商图助理】小程序过程中开发的一款组件,在使用中体验还是不错的,近期在公司项目【活动抽奖】小程序重构过程中我想到了曾经封装的这款组件,进行了少许的优化,以及文档说明并如到【活动抽奖】项目中,下方为该组件的代码,使用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)

  },


```


微信小程序,图片压缩,组件封装

手机扫码访问