首先创建一个utils.js文件(以下是文件中图片压缩方法)
/**
* APP端图片压缩
* 参数说明:
* img 图片url
* scale缩放比例 1-100
* callback 回调设置返回值
*/
export function translateapp(img, scale, callback) {
plus.io.resolveLocalFileSystemURL(img, (entry) => { //通过URL参数获取目录对象或文件对象
entry.file((file) => { // 可通过entry对象操作图片
console.log('压缩前图片信息:' + JSON.stringify(file)); //压缩前图片信息
if (file.size > 504800) { // 如果大于500Kb进行压缩
plus.zip.compressImage({ // 5+ plus.zip.compressImage 了解一下,有详细的示例
src: img, //src: 压缩原始图片的路径
dst: img.replace('.png', 'yasuo.png').replace('.PNG',
'yasuo.PNG').replace('.jpg', 'yasuo.jpg')
.replace('.JPG', 'yasuo.JPG'),
width: '40%', //dst: (String 类型 )压缩转换目标图片的路径,这里先在后面原始名后面加一个yasuo区分一下
height: '40%', //width,height: (String 类型 )缩放图片的宽度,高度
quality: scale, //quality: (Number 类型 )压缩图片的质量
overwrite: true, //overwrite: (Boolean 类型 )覆盖生成新文件
// format:'jpg' //format: (String 类型 )压缩转换后的图片格式
}, (event) => {
console.log('压缩后图片信息:' + JSON.stringify(event));
//返回压缩后的图片路径
callback(event.target);
}, function(err) {
console.log('Resolve file URL failed: ' + err.message);
});
} else { //else小于500kb跳过压缩,直接返回现有的src
callback(img);
}
});
}, (e) => { // 返回错误信息
console.log('Resolve file URL failed: ' + e.message);
});
}
/**
* H5端图片压缩
* 参数说明:
* imgSrc 图片url
* scale缩放比例 0-1
* type 返回图片类型 默认blob
* callback 回调设置返回值
*/
export function translate(imgSrc, scale, type , callback) {
var img = new Image();
img.src = imgSrc;
img.onload = function() {
var that = this;
var h = that.height; // 默认按比例压缩
var w = that.width;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var width = document.createAttribute("width");
width.nodeValue = w;
var height = document.createAttribute("height");
height.nodeValue = h;
canvas.setAttributeNode(width);
canvas.setAttributeNode(height);
ctx.drawImage(that, 0, 0, w,h);
var base64 = canvas.toDataURL('image/jpeg', scale);//压缩比例
canvas = null;
if(type == 'base64'){
callback(base64);
}else{
var blob = base64ToBlob(base64);
var blobUrl = window.URL.createObjectURL(blob);//blob地址
callback(blobUrl);
}
}
}
// base转Blob
export function base64ToBlob(base64) {
var arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
/**
* 小程序端图片压缩
* 参数说明:
* tempFilePaths:图片
*/
使用
<script>
import { translateapp, translate,mp_compressImage} from "@/utils.js"
methods:{
uni.chooseImage({
count: 6, //默认9
sizeType: [ 'original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['camera'], //从相册选择 album
success: function (res) {
//区分APP与H5不同端调用不同的方法
// #ifdef APP-PLUS
/**
* APP端图片压缩
* 参数说明:
* img 图片url
* scale缩放比例 1-100
* callback 回调设置返回值
*/
translateapp(res.tempFilePaths[0], 80, imgUrl => {
//打印压缩后返回的图片url
console.log(imgUrl );
})
// #endif
// #ifdef H5
/**
* H5端图片压缩
* 参数说明:
* imgSrc 图片url
* scale缩放比例 0-1
* type 返回图片类型:base64、blob(默认blob)
* callback 回调设置返回值
*/
translate(res.tempFilePaths[0], 0.7, ' ', imgUrl => {
//打印压缩后返回的图片url
console.log(imgUrl );
})
// #endif
}
});
}
</script>
小程序压缩
页面使用示例:
//template
<canvas canvas-id="canvas" id="canvas" type="2d" style="display: none;"></canvas>
//methods
/**
* 上传头像触点
*/
uploadIcon() {
let _this = this;
uni.chooseImage({
count: 1, // 头像只上传1张
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
success: async (chooseImageRes) => {
try {
const tempFilePaths = chooseImageRes.tempFilePaths;
//#ifdef MP-WEIXIN
//ios小程序会自动压缩
if (this.isIphoneX('iPhone')) {
//直接返回图片路径
} else {
_this.getImage(tempFilePaths[0], true)
}
//#endif
} catch (e) {
console.log(e)
}
},
fail(err) {
console.log(err)
}
})
},
/**
* @param {Object} type 是否需要压缩
*/
getImage(file, type=false) {
if (type) {
this.$common.utils.getImageObject(file, img => {
this.$common.utils.compressImg(img, res => {
this.uploadFile(res)
}, (err) => {
this.$common.checker.alertTip(err.errMsg || '图片压缩失败');
})
})
} else {
this.uploadFile(file)
}
},
const common = {
/**
* 清除文件
*/
clearFile() {
return new Promise((resolve) => {
// 把文件删除后再写进,防止超过最大范围而无法写入
const fsm = wx.getFileSystemManager(); //文件管理器
fsm.readdir({ // 获取文件列表
dirPath: wx.env.USER_DATA_PATH, // 当时写入的文件夹
success(res) {
console.log(res)
res.files.forEach((el) => { // 遍历文件列表里的数据
// 删除存储的垃圾数据
fsm.unlink({
filePath: `${wx.env.USER_DATA_PATH}/${el}`, // 这里注意。文件夹也要加上,如果直接文件名的话会无法找到这个文件
fail(e) {
console.log('readdir文件删除失败:', e)
}
});
})
resolve()
}
})
})
},
/**
* 获取图片信息
* @param {string} imgObj 图片对象path
* @param {function} fn 回调函数
* @returns {ojbect} cbParams
* {
* height: 722,
* width: 1366,
* type: 'png',
* path: '',
* orientation: 'up',
* errMsg: ''
* }
*/
getImageObject(src, fn) {
uni.getImageInfo({
src: src,
success(res) {
console.log(res)
fn(res)
}
})
},
/**
* 压缩图片
* @param {object} img 图片
* @param {function} fn 回调函数
*/
compressImg(img, fn, fail) {
//#ifdef MP-WEIXIN
//获取canvas
const selectorQuery = uni.createSelectorQuery()
selectorQuery.select('#canvas')
.fields({
//返回节点信息,文档中说只有当canvas的type为weldg时才能生效,但是经过测试是可以用的
node: true,
size: true
})
.exec(res => {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
canvas.height = img.height
canvas.width = img.width
let seal = canvas.createImage();
seal.src = img.path;
seal.onload = () => {
//画图
ctx.drawImage(seal, 0, 0, img.width, img.height)
//压缩
const url = canvas.toDataURL('image/jpeg',0.5)
//清除历史文件,否则可能会导致无法写入
this.clearFile().then(() => {
const FILE_BASE_NAME = 'tmp_base64src';
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(url) || [];
if (!format) {
fail && fail({errMsg: 'ERROR_BASE64SRC_PARSE'});
return;
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
//将base64转为文件流,输出临时文件上传
const buffer = uni.base64ToArrayBuffer(bodyData);
console.log('filePath',filePath)
const fsm = wx.getFileSystemManager();
fsm.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
fn(filePath)
},
fail(err) {
fail && fail(err)
}
})
})
}
})
//#endif
//#ifndef MP-WEIXIN
//5+自带的图片压缩
plus.zip.compressImage({
src: img.path,
quality: 0.1,
width: 50,
height: 50
}, (res) => {
console.log(res)
fn(res.target)
}, (err) => {
console.log(err)
fail && fail(err)
});
//#endif
}
}