本文来讲讲移动端html5的canvas画布生成缩略图的方法,手机端的网站已经是趋势,而且现在网速也很快,打开图片分分钟,所以我们没有必要用后端生成物理图片了。
公司的移动页面, 上传图片时缩略图是靠后端生成, 但是随着现在的手机越来越牛X(摄像头比数码相机还厉害~), 图片体积也越来越大.
一个几M的图, 也许我们只是用来生成一个100*100的小图, 上传到后端再生成缩略图就大大的浪费了, 而且提交表单的等待时间也非长久, 对用户体验也不好.
普通的web表单, 上传图片靠后端来生成缩略图很平常, 但有了HTML5, 针对移动Web开发可以考虑使用前端生成缩略图了.
写了个生成缩略图的jquery的插件, 主要参数:
width: 生成缩略图的宽; height: 生成缩略图的高;
fill: 图片小于缩略图尺寸时, 是否填充(false: 缩略图宽高自动缩放到适应图片, true: 缩略图尺寸不变)
background:生成图片填充背景(默认#fff, 设置null时, 背景透明)
type: 生成图片类型 ('image/jpeg' 或 'image/png')
size: 生成缩略图方式, 生成缩略图的效果主要参考了CSS3的background-size属性:
contain: 等比缩放并拉伸, 图片全部显示;
cover: 等比缩放并拉伸, 图片把容器完全覆盖;
auto: 图片不拉伸, 居中显示.
mark: 水印
文字水印: mark = {padding: 5, height: 18, text: 'test', color: '#000', font: '400 18px Arial'}
图片水印: mark = {padding: 5, src: 'mark.png', width: 34, height: 45};
stretch: 小图是否强制拉伸以适应缩略图的尺寸(size = auto/contain时)
success: 生成缩略图后 callback
大体思路如下:
首先判断是否支持fileReader(支持fileReader, canvas就不在话下了)
不支持的话: 不做任何操作, 默认的input type="file"上传, 靠后端生成缩略图.
支持的情况: input change时, 判断选择的文件是图片, 就创建一个隐藏的canvas, 并把图片画到canvas里,
因为要生成缩略图, 所以在canvas里画图的时候, 控制剪切坐标和被剪切的宽高就OK了.
另外可以加上水印, 图片水印或者文字水印加到canvas上面也是比较方便的.
最后 canvas.toDataURL 转成base64, post到后端(先把input type="file"移除, 再生成个新的input type="hidden"储存图片数据), 后端接收后直接保存为图片就OK了.
主要用到: FileReader和canvas, 一个用来读取本地图片, 一个用来生成缩略图.
做移动网页开发的同学可以考虑下.
实例:
html5页面
<h2>html5</h2>
<script src="/js/jquery-2.1.4.min.js"></script>
<link href="/css/base.css" rel="stylesheet" />
<script src="/js/ImgUpload.js"></script>
<script>
$(function () {
new H5ImgUpload.init("imgUpload", "myCanvas", 400);
$("#uploadimg").click(function () {
H5ImgUpload.sendImage("myCanvas", "/Test/WxImg/uploadimg");
});
new H5ImgUpload.init("imgUpload1", "myCanvas1", 200);
$("#uploadimg1").click(function () {
H5ImgUpload.sendImage("myCanvas1", "/Test/WxImg/uploadimg");
});
$("#uploadAllImg").click(function () {
H5ImgUpload.uploadAllImage(".Canvas", "/Test/WxImg/uploadAllImg");
});
});
</script>
<a class="addphoto">
<input type="file" id="imgUpload" class="imgUpload" name="file1" draggable="false" single accept="image/*">
</a>
<canvas id="myCanvas" class="Canvas" data-id="img1" style="width:150px;"></canvas>
<input type="button" id="uploadimg" value="上传" />
<div style="clear:both;"></div><br>
<a class="addphoto">
<input type="file" id="imgUpload1" class="imgUpload" name="file2" draggable="false" single accept="image/*">
</a>
<canvas id="myCanvas1" class="Canvas" data-id="img2" style="width:150px;"></canvas>
<input type="button" id="uploadimg1" value="上传" />
<br/>
<input type="button" id="uploadAllImg" value="上传所有图片" />
imageUpload.js
var MAX_HEIGHT = 300;
var H5ImgUpload = {
//obj=上传控件
//objCanvas=画布控件
//maxHeight=图片最大高度(像素)
init: function (obj, objCanvas, maxHeight) {
if (maxHeight <= 0)
maxHeight = MAX_HEIGHT;
//判断浏览器是否有FileReader接口
if (typeof FileReader == 'undefined') {
//alert("亲,您的浏览器无法使用图片本地预览");
//如果浏览器是ie
if ($.browser.msie === true) {
H5ImgUpload.render(objCanvas, $("#" + obj).val(), maxHeight);
}
//如果是不支持FileReader接口的低版本firefox 可以用getAsDataURL接口
else if ($.browser.mozilla === true) {
H5ImgUpload.render(objCanvas, $("#" + obj).val(), maxHeight);
}
} else {//支持FileReader接口
//showPicture(obj);
H5ImgUpload.showPicture(obj, objCanvas, maxHeight);
}
},
showPicture: function (obj, objCanvas, maxHeight) {
$("#" + obj).change(
function (e) {
for (var i = 0; i < e.target.files.length; i++) {
var file = e.target.files.item(i);
//允许文件MIME类型 也可以在input标签中指定accept属性
//console.log(/^image\/.*$/i.test(file.type));
if (!(/^image\/.*$/i.test(file.type))) {
continue; //不是图片 就跳出这一次循环
}
//实例化FileReader API
var freader = new FileReader();
freader.readAsDataURL(file);
freader.onload = function (e) {
H5ImgUpload.render(objCanvas, e.target.result, maxHeight);
}
}
});
},
render: function (objCanvas, src, maxHeight) {
// 创建一个 Image 对象
var image = new Image();
// 绑定 load 事件处理器,加载完成后执行
image.onload = function () {
// 获取 canvas DOM 对象
var canvas = document.getElementById(objCanvas);
// 如果高度超标
if (image.height > maxHeight) {
// 宽度等比例缩放 *=
image.width *= maxHeight / image.height;
image.height = maxHeight;
}
// 获取 canvas的 2d 环境对象,
// 可以理解Context是管理员,canvas是房子
var ctx = canvas.getContext("2d");
// canvas清屏
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 重置canvas宽高
canvas.width = image.width;
canvas.height = image.height;
// 将图像绘制到canvas上
ctx.drawImage(image, 0, 0, image.width, image.height);
// !!! 注意,image 没有加入到 dom之中
};
// 设置src属性,浏览器会自动加载。
// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
image.src = src;
},
sendImage: function (objCanvas, url) {
// 获取 canvas DOM 对象
var canvas = document.getElementById(objCanvas);
// 获取Base64编码后的图像数据,格式是字符串
// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。
var dataurl = canvas.toDataURL("image/png");
// 为安全 对URI进行编码
// data%3Aimage%2Fpng%3Bbase64%2C 开头
var imagedata = encodeURIComponent(dataurl);
var data = {
img64: imagedata
};
jQuery.ajax({
url: url,
data: data,
type: "POST",
// 期待的返回值类型
dataType: "json",
complete: function (xhr, result) {
if (result == 'timeout') {//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
alert("超时");
} else {
alert(xhr.responseText);
}
}
});
},
uploadAllImage: function (classCanvas, url) {
var arrayObj = new Array(); //创建一个数组
jQuery(classCanvas).each(function () {
var dataurl = this.toDataURL("image/png");
var obj = new Object();
obj.name = jQuery(this).attr("data-id");
obj.value = encodeURIComponent(dataurl);
arrayObj.push(obj);
});
var data = {
objImg64: JSON.stringify(arrayObj)
};
jQuery.ajax({
url: url,
data: data,
type: "POST",
// 期待的返回值类型
dataType: "json",
complete: function (xhr, result) {
alert(xhr.responseText);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (textStatus == "timeout")
{
alert("超时");
} else if (textStatus == "error")
{
alert(errorThrown);
}
}
});
}
};
后端控制器:
[HttpPost]
public JsonResult uploadAllImg()
{
string base64 = Server.UrlDecode(Request.Form["objImg64"]);// Request.Form["img64"].Replace("data:image/png;base64,", "");
JavaScriptSerializer js = new JavaScriptSerializer();
List<uploadImg> jg = js.Deserialize<List<uploadImg>>(base64);
string a1 = "";
string a2 = "";
foreach (var s in jg)
{
if (s.name == "img1")
{
a1 = s.name;
}
var _base64 = s.value.Replace("data:image/png;base64,", "");
byte[] arr = Convert.FromBase64String(_base64);
using (MemoryStream ms = new MemoryStream(arr))
{
using (Bitmap bmp = new Bitmap(ms))
{
bmp.Save(Server.MapPath("/") + "upload/img/" + NetProjectCommon.Utils.GetRamCode() + ".jpg", ImageFormat.Jpeg);
}
}
}
return Json(1);
}
Copyright © 广州京杭网络科技有限公司 2005-2024 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有