您的位置:首页 > Web前端 > HTML5

H5使用Base64和Canvas上传图片

2018-01-19 11:22 661 查看
    最近在做一个班级通知的H5页面,从拿到原型到开发出完整功能的过程中,解决了一些问题,现在记录一下发布通知时遇到的难点和解决方法。

一、调用手机摄像头和手机相册选取照片

1、由于使用的是最接近原生Android的mui框架,所以最开始是准备用mui的plus来调用camera和gallery方法,但是后来发现一直出现plusReady未定义的错误,写在plusReady中的代码没有执行。    在DCloud中找到原因如下,普通浏览器里没有plus环境,只有HBuilder真机运行和打包后才能运行plus api,且个人尝试在真机中也不能运行。公司使用mui在初始阶段,本人更是小白,到了这里最后还是决定使用JS来实现照片的选择和上传。
2、使用input标签调用摄像头和相册,accpet表示打开系统文件目录,capture表示可捕获到的系统设备,multiple表示多选。 ① <input type="file" accept="image/*" > // 打开相机或相册 ② <input type="file" accept="image/*" capture="camera"> // 打开相机,可以拍照 ③ <input type="file" accept="video/*" capture="camcorder"> // 打开录像机,可以录像 ④ <input type="file" accept="audio/*" capture="microphone"> // 打开录音机,可以录音     选择input标签后,觉得和已有的UI风格相差很大,界面显示如下:                                             


     可以设置 opacity:0 将已有的input格式隐藏,然后将文本信息居中显示。
<input style="opacity:0;width:1px" type="file" id="file_input" accept="image/*" multiple>选择图片</input>

二、Base64。

1、简介。     Base64是一种用64个字符【A-Z  a-z  0-9  + /】来表示任意二进制数据的方法,常用于在URL、Cookie、数字证书签名或网页中传输少量二进制数据。     将每3个字节Byte即3*8=24bit,转化为4组6个二进制位,然后在6位的前面补两个0,形成一个8位的字节,若剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='【解码时会自动去掉】。 通过查表获得4个编码后的字符,由于Base64把3字节的二进制数据编码为4字节的文本数据,所以长度增加33%左右。                 


2、为什么使用Base64。 ① 减少HTTP请求数,提高页面加载速度。对于只有几个KB大小的图片,进行HTTP请求附带的额外信息可能比图片本身还大,当请求量大时,数据传输会变慢【以data:image/*;base64开头】。 ② 将图片使用Base64编码后,可通过URL直接解码查看图片,即内嵌到网页中而不是去请求并加载进来。 ③ 可以防止因为一些相对路径等问题导致的图片404错误。
3、Base64的缺点。 ① Base64是一种通过查表的编码方法,不能用于加密,即使使用自定义的编码表也不行。 ② 当需要传输的图片在1M以上时【未确定临界值】,在网页中加载Base64会变得很慢,此时需对图片进行压缩处理。

三、使用Base64和Canvas保存图片的编码。

1、使用FileReader将文件转化为Base64编码。 ① 在H5中使用FileReader把文件读取到内存,并读取文件中的数据,以便对图片进行预览。 ② FileReader的readAsDataURL方法可以将读取的文件数据以DataURL的形式即Base64存储,可在客户端直接显示。
2、使用Canvas对图片重新绘制并设置压缩质量。 ① 将图片转化成Base64后,可以绘制到Canvas上并对图片进行编辑操作。 ② 当编辑或压缩完成后,可以使用Canvas的toDataURL方法输出新图片的Base64数据。
HTML:
<div class="row mui-input-row ">
<textarea id="container" name="txt" class="mui-input-clear question"
placeholder="请输入正文(必填,最多输入500个汉字)"></textarea>
<div class="add_picture_div">
<a href="#picture" class="add_picture"><img src="${base}/res/images/add.png"></a>
</div>

<div id="picture" class="mui-popover mui-popover-action mui-popover-bottom">
<ul class="mui-table-view">
<li class="mui-table-view-cell">
<input style="opacity:0;width:1px" type="file" id="file_input" accept="image/*" multiple>选择图片</input>
</li>
<li class="mui-table-view-cell"><a href="#"><b>取消</b></a></li>
</ul>
</div>
</div>
JavaScript:
var myHtml="";
window.onload = function(){
var result,input = document.getElementById("file_input");
if(typeof FileReader==='undefined'){
result.innerHTML = "抱歉,你的浏览器不支持 FileReader";
input.setAttribute('disabled','disabled');
}else{
input.addEventListener('change',readFile,false);
}
function readFile(){
var iLen = this.files.length;
for(var i=0;i<iLen;i++){
if (!input['value'].match(/.jpg|.gif|.png|.bmp/i)){  //判断上传文件格式
return alert("上传的图片格式不正确,请重新选择");
}
var reader = new FileReader();
var fileName = this.files[i].name; 	  // 获取文件名
var fileType = this.files[i].type;	  // 文件后缀
reader.readAsDataURL(this.files[i]);  // 转成base64,此方法执行完后,base64数据储存在reader.result里
reader.onload = function(e){
var image = new Image();		  // 创建一个image对象,供canvas绘图使用
image.src = this.result;		  // this.result即base64的数据
image.onload = function(){
var scale = 1;
var cvs = document.createElement('canvas');
if(this.width > 300 || this.height > 300){
if(this.width > this.height)
scale = 300 / this.width;
else scale = 300 / this.height;
}
cvs.width = scale * this.width;		// 计算等比缩小后图片宽
cvs.height = scale * this.height;
var ctx = cvs.getContext('2d');		// 返回一个用于在画布上二维绘图的环境
ctx.drawImage(this,0,0,cvs.width,cvs.height);
var newImage = cvs.toDataURL(fileType,0.7);	// 重新生成图片Base64,压缩质量即压缩率为0.7
myHtml += "<br><p style='text-align:center;'><img src='"+newImage+"'/></p>";
var aHtml = '<a href="#" class="add_picture"><img src="'+newImage+'"/></a>';
$(".add_picture_div").append(aHtml);
}
}
}
}
}
jQuery:
$.ajax({
url:'${base}/classedit/notice/noticePublish',
type:"post",
data:{
ownerId:$("#clsId").val(),		// 班级ID
listTitle:$("#title").val(),
txt:$("#container").val()+myHtml
},
success:function(result){
console.info(result);
if(result.status == true){
alert("发布成功!");
window.location.href='toNoticeListPage?userId=${userId!'' }';
}else{
alert("发布失败!");
window.location.reload();
}
}
});
让发布的通知以原样显示到详情页中,可以使用<pre>标签格式化 freemarker 取出的数据。pre 元素可定义预格式化的文本,被包围在 pre 元素中的文本通常会保留空格和换行符,存储到数据库中的数据会以原格式显示到页面中。
<div class="mui-media-body">
<h4>${cmsContentExt.title }</h4>
<h6 class="mt15">${cmsContentExt.author } ${cmsContentExt.releaseDate?string("yyyy-MM-dd HH:mm:ss") }</h6>
<h6 class="mui-ellipsis mt20 fong_gray">
<#if listCD ??>
<#list listCD as list>
${list.className }
</#list>
</#if>
</h6>
<span class="mt20 fong_gray"><pre>${cmsContentTxt.txt}</pre>&l
ac02
t;/span>
</div>

3、效果图:
① 发布通知:                                             


② 按Scale等比缩放图片像素:                                                               


③ 使用img{max-width:100%;} 设置,若图片大于屏宽则100%显示,图片小于屏宽则显示原图。                                                      


     至此,H5页面发布通知功能开发完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: