移动端Vue图片获取,压缩,预览组件-upload-img(H5+获取照片,压缩,预览)

2022-12-24,,,,

组件示例图

组件代码 upload_img.vue

  <div id="uploadImg">
<div class="upload_image_box" v-show="show1">
<div class="upload_image">
<div class="photo_box" @click="actionSheet()">
<img class="icon_photo" src="../../assets/images/icon_photo.png" />
<p><span>{{$t('m.btn_0011')}}</span></p>
</div>
</div>
</div>
<div class="uploaded" v-show="show2">
<div v-for="(item,index) in imgLists" class="imgItem">
<img @click="deleteImg(index)" class="delete" src="../../assets/images/icon_x.png">
<img :src="item" class="img" @click="previewPicture(index)">
</div>
<div class="imgUpload" @click="actionSheet()">
<img class="icon_photo" src="../../assets/images/icon_photo.png" />
<p><span>{{$t('m.btn_0011')}}</span></p>
</div>
</div>
</div>
</template> <script>
import {Toast, Indicator} from "mint-ui"
export default({
props: [
'imgList',
'showUpload',
'showUploaded',
'maxPic',//用户传的最大的照片数目
'zipTo' // 压缩到多少KB(可选,默认到1024K)
],
data() {
return {
show1: true,
show2: false
}
},
computed: {
imgLists() {
return this.imgList || []
},
getMaxPic() {
return this.maxPic*1 || 1
}
},
watch: {
imgLists(newValue, oldValue) {
if(newValue.length > 0){
this.show1 = false;
this.show2 = true;
} else {
this.show1 = true;
this.show2 = false;
}
}
},
methods: {
actionSheet() {
let that = this
plus.nativeUI.actionSheet({
title: "获取照片",
cancel: "取消",
buttons: [
{
title: "拍照"
},
{
title: "相册"
},
]
},
function(e) { //点击回调
switch(e.index) {
case 0:
break;
case 1:
that.cameraImg(); /*拍照*/
break;
case 2:
that.galleryImg(); /*打开相册*/
break;
default:
break;
}
}
);
},
galleryImg() {
let that = this;
plus.gallery.pick(
function(e) {
for (var i in e.files) {
var path = e.files[i]; // file:///storage/emulated/0/截屏、超级截屏_20180803_112739.png
if (that.imgLists.length < that.getMaxPic) {
plus.io.resolveLocalFileSystemURL(path, function(entry) { //entry 请求到的目录或文件对象
var fileSystem = entry.fileSystem
var fileInfo = {};
entry.file(function(file){ // 获取文件信息
fileInfo = file;
let zipTo = that.zipTo; // KB
that.zipPicture(path, fileInfo, zipTo)
.then(function(zipObj){
if(zipObj && zipObj.target){
Indicator.open();
console.log('107:', that.imgLists, zipObj.target,!that.imgLists.includes(zipObj.target))
if(!that.imgLists.includes(zipObj.target)){
that.getBase64(zipObj.target) //zipObj.target -压缩后的文件所在的路径
.then(function(dataURL){ //dataUrl -压缩后的文件的base64编码
that.dataURLtoFile(dataURL, fileInfo.name)
.then(function(f){ // f - base64转成文件后的文件对象
let fileBigObj = {
path: zipObj.target,
file: f
}
console.log(fileBigObj);
that.$emit('pickPic',fileBigObj)
return fileBigObj;
})
})
}else{
Toast({message: '同一张图片不能重复提交'})
}
}
})
.catch(function(zipErr){
that.zipErrHandle(zipErr, fileInfo)
})
})
})
} else {
that.$alert(i18n.t('m.msg_0005')+`${that.getMaxPic}`+i18n.t('m.msg_0007'));
break;
}
}
},
function(error) {
Indicator.close();
if(error.code == 12){
Toast({message: '用户取消'})
}else{
that.galleryPermission(error)
}
},
{
filter: "image",
multiple: true, // 设置了此项,选择成功返回的是一个包含键名为files的路径数组的对象,否则为单一路径;
maximum: that.getMaxPic - that.imgLists.length
});
},
cameraImg() { // 调用相机
let that = this;
let c = plus.camera.getCamera();
let hasCamera = that.cameraPermission()// 相机权限
if(!hasCamera) return
c.captureImage(function(e) {
//获取操作文件或目录对象
plus.io.resolveLocalFileSystemURL(e, function(entry) { //entry 请求到的目录或文件对象
that.showUpload = false;
that.showUploaded = true;
var path = entry.toLocalURL() //toLocalURL: 获取目录路径转换为本地路径URL地址
//压缩图片
plus.io.resolveLocalFileSystemURL(path, function(entry) { //entry 请求到的目录或文件对象
var fileSystem = entry.fileSystem
var fileInfo = {};
entry.file(function(file){ // 获取文件信息
fileInfo = file;
let zipTo = that.zipTo; // KB
that.zipPicture(path, fileInfo, zipTo)
.then(function(zipObj){
if(zipObj && zipObj.target){
Indicator.open();
if(!that.imgLists.includes(zipObj.target)){
that.getBase64(zipObj.target) //zipObj.target -压缩后的文件所在的路径
.then(function(dataURL){ //dataUrl -压缩后的文件的base64编码
that.dataURLtoFile(dataURL, fileInfo.name)
.then(function(f){ // f - base64转成文件后的文件对象
let fileBigObj = {
path: zipObj.target,
file: f
}
console.log(fileBigObj);
that.$emit('pickPic',fileBigObj)
return fileBigObj;
})
})
} else {
Toast({message: '同一张图片不能重复提交'})
}
}
})
.catch(function(zipErr){
that.zipErrHandle(zipErr, fileInfo)
})
})
}) }, function(e) {
console.log("读取拍照文件错误:" + e.message);
});
}, function(error) {
if(error.code == 11){
Toast({message: '用户取消'})
}
}, {
filename: "_doc/" //拍照文件存放的路径
})
},
deleteImg(index) {
let deletePic = this.imgLists[index]
this.$emit('deletePic', deletePic)
},
/**
* @description 打开相册失败,请求系统权限
* @param {Error} e
*/
galleryPermission(e) {
var galleryPermission = plus.navigator.checkPermission("GALLERY");
if (plus.os.name == "iOS") {
if (e.code == 8) {
plus.nativeUI.alert("您的相册权限未打开,请在当前应用设置-隐私-相册来开打次权限", function(event){
plus.runtime.openURL('prefs:root=Privacy');
})
}
} else if (plus.os.name == "Android") {
if (e.code != 12) {
plus.nativeUI.alert("您的相册权限未打开,请在应用列表中将您的权限打开", function() {
// var android = plus.android.importClass('com.android.settings');
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass("android.content.Intent");
var mIntent = new Intent('android.settings.APPLICATION_SETTINGS');
main.startActivity(mIntent);
});
}
}
},
cameraPermission() {
var cameraPermission = plus.navigator.checkPermission("CAMERA");
if( cameraPermission == "denied" ){// 阻塞
if (plus.os.name == "iOS") {
plus.nativeUI.alert("您的相机权限没有打开,请在当前应用设置-隐私-相机来开打次权限", function(event){
plus.runtime.openURL('prefs:root=Privacy');
})
} else if (plus.os.name == "Android") {
plus.nativeUI.alert("您的相机权限没有打开,请在应用列表中将权限打开", function() {
// var android = plus.android.importClass('com.android.settings');
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass("android.content.Intent");
var mIntent = new Intent('android.settings.APPLICATION_SETTINGS');
main.startActivity(mIntent);
});
}
return false
}else{
return true
}
},
// zipPicture(pth, cb) {
// return new Promise(function(resolve, reject){
// let conf = {
// src: pth,
// dst:pth,
// overwrite:true,
// quality: 50
// };
// plus.zip.compressImage(conf, function(data) {
// resolve(data)
// }, function(err) {
// Toast({message:'图片压缩失败,错误编码:'+err.code})
// reject(err);
// });
// })
// },
previewPicture(index) {
plus.nativeUI.previewImage(this.imgLists,{current:index});
},
zipPicture(pth, fileInfo, zipTo) {
return new Promise(function(resolve, reject){
let zipName = fileInfo.name,
quality = 0.50;
typeof zipTo === 'number' ? zipTo>0 ? zipTo = zipTo :zipTo = 1024 : zipTo = 1024; //默认压缩到1M
zipTo < fileInfo.size ? quality = zipTo / fileInfo.size : quality = 1;
let conf = {
src: pth,
dst: '_doc/'+zipName,//pth, // 转换目标图片的路径
overwrite:false, //true, // 是否覆盖
quality: quality * 100 // 取值(0,100]
};
plus.zip.compressImage(conf, function(data) {
resolve(data)
}, function(err) {
// plus.nativeUI.alert('图片压缩失败,错误编码:'+err.code)
reject(err);
});
})
},
dataURLtoFile(dataurl, filename) {//将base64转换为文件
//atob()- window内置的函数;ASCII码转binary ;不支持非ASCII码转换,
//btoa()- window内置函数;binary转ASCII;不支持非ASCII码转换,
return new Promise(function(resolve, reject){
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
var file = new File([u8arr], filename, {type:mime})
resolve(file);
})
},
getBase64(url){
return new Promise(function(resolve, reject){
var canvas = document.createElement('canvas'),//创建canvas元素
dataURL= '',
ctx = canvas.getContext('2d'),
img = new Image; //通过构造函数来创建的 img 实例,在赋予 src 值后就会立刻下载图片,相比 createElement() 创建 <img> 省去了 append(),也就避免了文档冗余和污染
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img,0,0,);
dataURL = canvas.toDataURL('image/jpeg', 1);
resolve(dataURL)
// callback?callback(dataURL):null; //调用回调函数
canvas = null;
};
img.src = url; // 图片预览
})
},
zipErrHandle(zipErr, fileInfo) { // 压缩失败
let that = this;
if(zipErr.code == -5){ // 错误编码为-5--该路径已经存在该文件;跳过压缩,直接获取原来存在的文件
var zipRelatePath = "_doc/"+ fileInfo.name;
plus.io.resolveLocalFileSystemURL( zipRelatePath, function(entry){
var zipLocalURL = entry.toLocalURL()
console.log('336:', that.imgLists, zipLocalURL, !that.imgLists.includes(zipLocalURL))
if( !that.imgLists.includes(zipLocalURL)){
that.getBase64(zipLocalURL) //zipLocalURL -压缩后的文件所在的'绝对路径'
.then(function(dataURL){ //dataUrl -压缩后的文件的base64编码
that.dataURLtoFile(dataURL, fileInfo.name)
.then(function(f){ // f - base64转成文件后的文件对象
let fileBigObj = {
path: zipLocalURL,
file: f
}
console.log(fileBigObj);
that.$emit('pickPic',fileBigObj)
return f;
})
})
} else {
Toast({message: '同一张图片不能重复提交'})
}
}, function(){ })
}
}
}
})
</script> <style lang="less" scoped="scoped">
#uploadImg{
.upload_image_box{padding: 34px;width: 100%;box-sizing: border-box;background: #fff;
.upload_image{background: #f2f2f2;width: 100%;border: 1px dashed #e6e6e6;/*no*/border-radius: 10px;padding: 110px 0;
.photo_box{width: 100%;
.icon_photo{width: 44px;height: 40px;position: relative;left: 50%;margin-left: -22px;}
p{font-size: 24px;/* px */color: #999999;text-align: center;margin: 0;}
}
}
}
.uploaded{padding: 34px;width: 100%;box-sizing: border-box;background: #fff;
.imgItem{width: 214px;height: 214px;display: inline-block;border: 2px dashed #e5e5e5;border-radius: 20px;position: relative;vertical-align: top;margin-right: 20px;
.delete{width: 30px;height: 30px;position: absolute;right: 0;}
.img{width: 100%;height: 100%;border-radius: 20px;}
}
.imgUpload{width: 214px;height: 214px;display: inline-block;background: #f2f2f2;padding: 66px 0;box-sizing: border-box;border: 2px dashed #e5e5e5;border-radius: 20px;
.icon_photo{width: 44px;height: 40px;position: relative;left: 50%;margin-left: -22px;}
p{font-size: 24px;/* px */color: #999999;text-align: center;margin: 0;}
}
}
}
</style>

父组件使用代码

<template>
<upload_img :imgList='imgList' :maxPic='"6"' @pickPic='pickPic($event)' @deletePic='deletePic' :zipTo = 'zipTo'></upload_img>
</template> <script>
import upload_img from '../../../common/upload_img' export default ({
data() {
return {
imgList: [],
zipTo: 1024 // KB
}
},
components: {
upload_img
},
methods: {
pickPic(rest){ /*选择照片成功后回调函数*/
setTimeout(function(){
Indicator.close();
},200)
let that = this;
let fickedFile = rest.file; // 选中的文件对象
rest && that.imgList.push(rest.path)
console.log(rest);
//... 上传图片逻辑
},
deletePic(rest) {
let that = this;
let index = that.imgList.indexOf(rest);
that.imgList.splice(rest, 1)
}
}
})
</script>

移动端Vue图片获取,压缩,预览组件-upload-img(H5+获取照片,压缩,预览)的相关教程结束。

《移动端Vue图片获取,压缩,预览组件-upload-img(H5+获取照片,压缩,预览).doc》

下载本文的Word格式文档,以方便收藏与打印。