思路如下:
使用原生input标签实现图片上传时,如果你的写法是如下所示:
<input
type="file"
id="upload_file"
@change="fileChange($event)"
style="display: none"
data-type="front"
>
fileChange(el) {
if (!el.target.files[0].size) return;
let currentType = el.target.dataset.type
this.fileList(el.target.files,currentType);
el.target.value = ''
},
// 格式限制
fileList(files,currentType) {
for (let i = 0; i < files.length; i++) {
if(files[i].type=='image/jpeg'||files[i].type=='image/jpg'||files[i].type=='image/png'||files[i].type=='image/webp'){
this.fileAdd(files[i],currentType);
} else {
return
}
}
},
// 获取选择的图片的base64地址
fileAdd(file,currentType) {
let reader = new FileReader();
reader.vue = this;
reader.readAsDataURL(file);
let _this = this;
reader.onload = function () {
file.src = this.result; // 图片的base64地址
}
}那你在手机中表现为:可能部分安卓只能从相册中选择照片,ios则可以拍摄、相册二选一。
为了在安卓手机也可以实现(拍摄、相册二选一)的需求,我们尝试给input标签增加accept="image/*"的属性,然后引出了新的问题
问题描述:发现在部分老机型(2016年买的手机)中当用户拍照后并没有触发input的change事件,网上有讨论说是input的value值没有改变,但如你所见,input标签上我们并没有绑定任何的value值。
最终,因为我们要实现的h5页面仅在微信浏览器环境使用,故我们改成在微信浏览器环境调用wx.chooseImage这个api来实现,关键代码如下所示:
fileClick(type) {
var that=this
if(that.supportWxApi) { // 微信环境,用微信提供的api
wx.chooseImage({
count: 1, // 最多可以选择的图片张数,默认9
sizeType: ['original','compressed'], // 可以指定是原图还是压缩图,默认二者都有'original', 'compressed'
sourceType: ['album','camera'], // 可以指定来源是相册还是相机,默认二者都有'album', 'camera'
success: function (res) {
/**
* 获取图片数据
*/
wx.getLocalImgData({
localId: res.localIds[0].toString(),
success: function (result) {
const localData = result.localData;
let imageBase64 = '';
if (localData.indexOf('data:image') == 0) {
//苹果的直接赋值,默认生成'data:image/jpeg;base64,'的头部拼接
imageBase64 = localData;
} else {
//此处是安卓中的坑!在拼接前需要对localData进行换行符的全局替换
//此时一个正常的base64图片路径就完美生成赋值到img的src中了
imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
}
if(type=='front') {
that.compressImg(imageBase64,function(base64Codes){
console.log('base64Codes',base64Codes)
})
} else if(type=='back') {
that.compressImg(imageBase64,function(base64Codes){
console.log('base64Codes',base64Codes)
})
}
}
});
}
});
} else { // 非微信环境,用原生的input上传图片
// 用click事件去触发change事件
document.getElementById('upload_file').click()
}
},图片压缩
服务器那边对图片的大小有要求,故我们利用canvas来实现图片等比例压缩,
压缩图片的关键函数代码如下所示:
// 图片压缩
compressImg(path,callback) {
var img = new Image();
img.src = path;
var objCompressed = {}
var _this = this;
img.onload = function() {
//默认压缩后图片规格
var quality = 0.7;
var w = this.width;
var h = this.height;
//实际要求
if (w > h) {
let scale = h/w
h = 1300;
w = h/scale;
} else {
let scale = w/h
w = 1300;
h = w/scale;
}
// w = objCompressed.width || w;
// h = objCompressed.height || (w / scale);
//生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 创建属性节点
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(this, 0, 0, w, h);
var base64 = canvas.toDataURL('image/jpeg', quality);
callback(base64);//回调函数返回base64的值
}
},图片压缩函数的使用方式如下:
that.compressImg(imageBase64,function(base64Codes){
// imageBase64是压缩前的图片
console.log('压缩后的大小:',that.showSize(base64Codes))
})获取base64图片的大小,返回kb数字
showSize(base64url) {
//把头部去掉
let str = base64url.replace('data:image/jpeg;base64,', '');
// 找到等号,把等号也去掉
let equalIndex = str.indexOf('=');
if (str.indexOf('=') > 0) {
str = str.substring(0, equalIndex);
}
// 原来的字符流大小,单位为字节
let strLength = str.length;
// 计算后得到的文件流大小,单位为字节
let fileLength = parseInt(strLength - (strLength / 8) * 2);
// 由字节转换为kb
let size = "";
size = (fileLength / 1024).toFixed(2);
let sizeStr = size + "";
let index = sizeStr.indexOf(".");
let dou = sizeStr.substr(index + 1, 2);
if (dou == "00") {
return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2)
}
return size;
},版权声明:本文为tt18473481961原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。