先上效果
上传图片后(设置了最多上传3张图片,三张后上传按钮消失)
点击图片放大,可以使用删除和旋转按钮 (旋转功能主要是因为ios手机拍照后上传会有写图片被自动旋转,通过旋转功能可以调正)
html页面
需要引入weui.min.css 不然没法渲染样式, 将下面的代码放在需要上传文件的地方就行了,如果不需要图片旋转功能, 可以直接删掉那个div, 改不改js无影响
addPhoto.html
<!--图片缩略图--> ????????<div class="weui-cells weui-cells_form" style="margin-top:0px;"> ???????????????<div class="weui-cell"> ?????????????????????<div class="weui-cell__bd"> ???????????????????????<div class="weui-uploader"> ???????????????????????????<div class="weui-uploader__hd"> ???????????????????????????????????<p class="weui-uploader__title" style="font-size: 14px;">照片:</p> ????????????????????????????????<div class="weui-uploader__info"><span id="curNum">0</span>/3</div> ???????????????????????????</div> ???????????????????????????<div class="weui-uploader__bd"> ???????????????????????????????<ul class="weui-uploader__files" id="uploaderFiles"></ul> <!--缩略图显示--> ???????????????????????????????<div class="weui-uploader__input-box"> ???????????????????????????????????????<form action="" id="upBox_add" onsubmit="return false;"> ???????????????????????????????????????<input id="uploaderInput" name="file" class="weui-uploader__input zjxfjs_file" type="file" ?capture="camera" accept="image/png,image/jpg,image/gif,image/JPEG" multiple=""></input> ????????????????????????????????????</form> ???????????????????????????????</div> ???????????????????????????</div> ???????????????????????</div> ???????????????????</div> ???????????????</div> ???????????</div> ????????<!--放大图片显示--> ?????????<div class="weui-gallery" id="gallery"> ?????????????????<span class="weui-gallery__img" id="galleryImg" style="bottom: 12%;"></span> ?????????????????<div class="weui-gallery__opr" style="width:50%;"> ???????????????????<a href="javascript:" class="weui-gallery__del"> ???????????????????????<i class="weui-icon-delete weui-icon_gallery-delete"></i> ???????????????????</a> ???????????????</div> ????????????????<!-- 图片旋转按钮--> ????????????????<div class="weui-gallery__opr2" style="z-index: 1200;width:50%;position: absolute;bottom:0;right:0;background-color: #0d0d0d;color: #fff;line-height: 60px;text-align: center;"> ???????????????????<a href="javascript:" class="weui-gallery__rot"> ???????????????????????<img src="/images/report/rotate.png" style="vertical-align: middle;"/> ???????????????????</a> ?????????????????</div> ????????</div>
<!--图片上传时, 给出上传提示, 并且不可操作数据, 上传完成去掉提示-->
<div id="loading" style="display:none; width:100%;height:100%;position:absolute;opacity: 0.5;z-index: 1001;">
<div id="inner" style="display:none;width:22%; position:absolute; left:45%; top:33%;font-size: 16px;font-weight: bold;">
<p>正在上传...</p>
</div>
</div>
然后在addPhoto.js中调用上传图片的方法(上传图片的方法写在了另一个js中)
addPhoto.js
var data={
?imgPathList:[],
?imgPath:‘‘,
?imgNum:0,//原有图片的数量,会根据删除而减少,新增的值为0
?imgArr:null
?}
var add = { ???template: ‘#add‘, ???data: function(){ ???????return data; ???}, ???created: function () { ???????var self = this; ???}, ???mounted:function(){//判断当前操作系统是安卓还是ios , 电脑浏览器使用可以去掉这个判断,加上也不影响 ???????var u = navigator.userAgent, ????????app = navigator.appVersion; ???????????????var isAndroid = u.indexOf(‘Android‘) > -1 || u.indexOf(‘Linux‘) > -1; ????????var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); ????????????????if (isAndroid) { ???????????$("#upBox_add").find("input[type=‘file‘]").attr("capture","camera"); ???????} ???????if (isIOS) { ???????????$("#upBox_add").find("input[type=‘file‘]").removeAttr("capture"); ???????} ?????????}, ???methods: {
loadingOpen:function () {
$(‘#loading‘).css(‘display‘,‘block‘);
$(‘#inner‘).css(‘display‘,‘block‘);//显示上传提示
},
loadingClose:function () {
$(‘#loading‘).css(‘display‘,‘none‘);
$(‘#inner‘).css(‘display‘,‘none‘);
}, ????????upload:function () {
???????????????uploadImg("/xxx/xxx");//传的参数是图片上传的接口, 用于ajax上传 ?????????},
????????addToDB:function(){
?if(0 != addReport_data.imgPathList.length){
????data.imgPath = data.imgPathList.join(",");
???}
?????????????//我这里用的是vue的框架,根据自己的框架修改保存到数据库的方法
Vue.resource("xxxx).save(data).then(function(response){
});
????????}}
图片上传的js
upload.js
Array.prototype.indexOf = function(val) { ???for (var i = 0; i < this.length; i++) { ???????if (this[i] == val) return i; ???} ???return -1;};Array.prototype.removeVal = function(val) { ???var index = this.indexOf(val); ???if (index > -1) { ???????this.splice(index, 1); ???}};/** 三个参数 file:一个是文件(类型是图片格式), w:一个是文件压缩的后宽度,宽度越小,字节越小 objDiv:一个是容器或者回调函数 photoCompress() */function photoCompress(file,w,objDiv){ ???var reader=new FileReader(); ???/*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/ ???reader.readAsDataURL(file); ???reader.onloadend=function(e){ ???????var re=this.result; ???????canvasDataURL(re,w,objDiv); ???}}function canvasDataURL(path, obj, callback){ ???var img = new Image(); ???img.src = path; ???img.onload = function(){ ???????var that = this; ???????// 默认按比例压缩 ???????var w = that.width, ???????????h = that.height, ???????????scale = w / h; ???????w = obj.width || w; ???????h = obj.height || (w / scale); ???????var quality = 0.7; ?// 默认图片质量为0.7 ???????//生成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(that, 0, 0, w, h); ???????// 图像质量 ???????if(obj.quality && obj.quality <= 1 && obj.quality > 0){ ???????????quality = obj.quality; ???????} ???????// quality值越小,所绘制出的图像越模糊 ???????var base64 = canvas.toDataURL(‘image/jpeg‘, quality); ???????// 回调函数返回base64的值 ???????callback(base64); ???}}/** * 将以base64的图片url数据转换为Blob * @param urlData * 用url方式表示的base64图片数据 */function convertBase64UrlToBlob(urlData){ ???var arr = urlData.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 b = new Blob([u8arr], {type:mime}); ???return b;}var uploadImg="";$(function() { ???var files; ???var filearr = []; ???var allImgSize=0; ???var tmpl = ‘<li class="weui-uploader__file" style="background-image:url(#url#)"></li>‘, ???????$gallery = $("#gallery"), ???????$galleryImg = $("#galleryImg"), ???????$uploaderInput = $("#uploaderInput"), ???????$uploaderFiles = $("#uploaderFiles"); ???????//选好图片触发 ???$uploaderInput.on("change", function(e) { ???????var src, url = window.URL || window.webkitURL || window.mozURL; ???????files = e.target.files; ????????if(files.length > 3){//一次最多上传3张图片 ???????????alert("图片数量大于3张,请重新选择!"); ???????????return; ???????} ???????if((filearr.length + files.length) <= 3){//判断所选的总图片数是否不大于3, 大于3张不能上传 ???????????var curNum =$("#curNum"); ???????????var vehLen=0; ???????????if(addReport_data.imgArr!=null){ ???????????????vehLen=addReport_data.imgArr.length; ???????????} ???????????for(var i = 0, len = files.length, end = len-1; i < len; i++) { ??????????????????????????????var curI=i; ???????????????var imgSize = files[i].size; ???????????????if(imgSize>1024*1024*5){//大于5M给出提示 ???????????????????alert("上传的第"+(i+1)+"张图片超过了5M!"); ???????????????????continue; ???????????????}else{ ???????????????????//压缩开始 ???????????????????var fileObj=files[i]; ??????????????????if(fileObj.size/1024 > 1025) { //大于1M,进行压缩上传 ???????????????????????photoCompress(fileObj, { ???????????????????????????quality: 0.1 ???????????????????????}, function(base64Codes){ ???????????????????????????var bl = convertBase64UrlToBlob(base64Codes); ???????????????????????????var form = new FormData(); ????????????????????????????form.append("file", bl,Date.parse(new Date())+".jpg");//将压缩后的图片编程文件对象 ???????????????????????????allImgSize+=bl.size; ???????????????????????????if(bl.size/1024 < 1024){ ???????????????????????????????filearr.push(form.get("file")); ???????????????????????????} ???????????????????????????if(curI==end){ ???????????????????????????????curNum.text(vehLen+filearr.length); ???????????????????????????} ???????????????????????????form.delete("file");//删除存入的压缩后的文件对象, 保证每次压缩只有当前被压缩的对象 ???????????????????????}); ???????????????????}else{ //小于等于1M 原图上传 ???????????????????????filearr.push(files[i]); ???????????????????????allImgSize+=files[i].size; ???????????????????} ???????????????????//压缩结束 ????????????????????????if(url) { ???????????????????????src = url.createObjectURL(fileObj); ???????????????????} else { ???????????????????????src = e.target.result; ???????????????????} ???????????????????$uploaderFiles.append($(tmpl.replace(‘#url#‘, src))); ???????????????} ???????????} ???????????curNum.text(vehLen+filearr.length); ???????????if(filearr.length == 3){//如果已经选择了3张图片,隐藏上传按钮 ???????????????$(‘.weui-uploader__input-box‘).css(‘display‘,‘none‘); ???????????} ????????}else{ ????????????alert("图片总数超过3张,请重新选择!"); ????????????return; ????????} ???}); ???var index; //第几张图片 ???var current = 0;//旋转多少度 ???$uploaderFiles.on("click", "li", function() { ???????index = $(this).index(); ???????$galleryImg.attr("style", this.getAttribute("style")); ???????$gallery.fadeIn(100); ???????current = 0; ???}); ???$galleryImg.on("click", function() { ???????$gallery.fadeOut(100); ???}); ???????//图片旋转 ???$(".weui-gallery__opr2").click(function() { ???????current += 90; ???????$("#galleryImg").css(‘transform‘, ‘rotate(‘ + current + ‘deg)‘); ???}); ???????//删除图片 ???$(".weui-gallery__del").click(function() { ???????$("#upBox_add").find(‘input‘).val(‘‘);//每次删除图片后,置空input框 ???????//$uploaderInput.attr(‘type‘,‘text‘);//第二种方法,更改input的属性, 实现重复上传
???????var num=index-addReport_data.imgNum; ???????allImgSize-=filearr[num].size; ???????filearr.splice(num, 1);//删除刚新增的图片,如果是新增的,原有图片(vehiclePicNum)为0 ???????$uploaderFiles.find("li").eq(index).remove(); ???????var vehLen=0; ???????if(data.imgArr!=null){ ???????????vehLen=data.imgArr.length; ???????} ???????$("#curNum").text(vehLen+filearr.length); ???????if(filearr.length < 3){//判断删除后,上传图片是否不大于3, 不大于,显示上传按钮 ???????????$(‘.weui-uploader__input-box‘).css(‘display‘,‘block‘); ???????} ???????$gallery.fadeOut(100); ??????????}); ???uploadImg=function(upUrl) { ???????if(filearr.length>0){ ???????????if(filearr.length<=3){ ???????????????var imgList = new FormData($("#upBox_add")[0]); ?//formData提交 ???????????????imgList.delete("file"); ???????????????for(var i =0;i<filearr.length;i++){ ???????????????????imgList.append("file", filearr[i]); ???????????????} ???????????????//上传所有的图片 ???????????????if(allImgSize<1024*1024*10){ ???????????????????add.methods.loadingOpen();//上传中 ???????????????????submitPicture(upUrl, imgList); ???????????????}else{ ???????????????????alert("上传图片的总大小不能超过10M!"); ???????????????} ???????????}else{ ???????????????alert("最多只能上传3张照片!"); ???????????????return false; ???????????} ???????}else{//如果没有选择图片 ???????????add.methods.addToDB(); ???????} ???}});//上传(将文件流数组传到后台)function submitPicture(url,data) { ??????$.ajax({ ???????type: "post", ???????url: url, ???????async: true, ???????data: data, ???????//下面这两个要写成false,要不然上传不了。 ???????processData: false, ???????contentType: false, ???????success: function(response) {//我这里上传接口返回的是json字符串,所以转成了对象后通过for循环将图片url存到数组中,方便html循环展示
response = JSON.parse(response);var reArray=response.data; ???????????????for(var i=0;i<reArray.length;i++){ ???????????????????data.imgPathList[i] = reArray[i].src; ???????????????} ???????????????add.methods.loadingClose();//关闭上传提示 ???????????????add.methods.addToDB();//调用保存方法,添加到数据库 ??????}, ???????error: function(xhr) { ???????} ???});}
其中使用了FormData对象, 具体用法请看: https://www.cnblogs.com/gczmn/p/9437935.html
以上js都是经过删减的, 去掉了多余的东西, 可能会有一些遗漏, 通过调试基本都能解决
html + js 实现图片上传,压缩,预览及图片压缩后得到Blob对象继续上传问题
原文地址:https://www.cnblogs.com/gczmn/p/9438530.html