很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的。但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 5 步。步骤繁琐不说,当很多用户上传图片的时候也很影响服务器性能。

HTML5 的出现让我们可以更方便的实现这一需求。虽然这里所说的技术都貌似有点过时了(前端界的“过时”,你懂的),但还是有些许参考价值。在这里我只说一下要点,具体实现同学们慢慢研究。

下面奉上我自己写的一个demo,在输入框中选好自己服务器 url, 生成好图片后点击 Submit 上传,然后自己去服务器里看看效果吧~~

浏览器要求支持以下 Feature:

代码直接从现有项目移植过来,没有经过“太多的”测试,写的很乱,也没注释,大家就慢慢看吧。。。重点就在 js 脚本的 28 行,clipImage 函数中,同学们可以直接跳过去看。

http://jsfiddle.net/windwhinny/d5qan0q7/点击预览

第一步:获取文件

HTML5 支持从 input[type=file] 元素中直接获取文件信息,也可以读取文件内容。我们用下面代码就可以实现:

$('input[type=file]').change(function(){
var file=this.files[0];
// continue ...
});

第二部:读取文件,并生成 Image 元素

这一步就需要用到 FileReader 了,这个类是专门用来读取本地文件的。纯文本或者二进制都可以读取,但是本地文件必须是经过用户允许才能读取,也就是说用户要在input[type=file]中选择了这个文件,你才能读取到它。

通过 FileReader 我们可以将图片文件转化成 DataURL,就是以 data:image/png;base64, 开头的一种URL,然后可以直接放在 image.src 里,这样本地图片就显示出来了。

$('input[type=file]').change(function(){
var file=this.files[0]; var reader=new FileReader();
reader.onload=function(){
// 通过 reader.result 来访问生成的 DataURL
var url=reader.result;
setImageURL(url);
};
reader.readAsDataURL(file);
}); var image=new Image();
function setImageURL(url){
image.src=url;
}

Image 就是在 html 里的 <img> 标签,所以可以直接插入到文档流里。

第三步:获取裁剪坐标

这一步没啥好说的,实现的方法也很多,需要获得下面四个裁剪框的坐标:

  • Y坐标
  • X坐标
  • 高度
  • 宽度

如下图所示:

第四部:裁剪图片

这是时候我们就需要用到 canvas 了,canvas 和图片一样,所以新建 canvas 时就要确定其高宽。这里我们还运用到 image.naturalHeight 和 image.naturalWidth 这两个属性来获取图片原始尺寸。

将图片放置入 canvas 时需要调用 drawImage ,这个接口参数比较多,在 MDN 上有详细的说明。

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

因为我们用 canvas 只是用于裁剪图片的,所以需要新建一个 canvas 让它的尺寸和裁剪之后图片的尺寸相等,此时 canvas 就相当与我们的裁剪框。运用这个函数还可以将大图缩放成小图,同学们自己研究吧。

// 以下四个参数由第三步获得
var x,
y,
width,
height; var canvas=$('<canvas width="'+width+'" height="'+height+'"></canvas>')[0],
ctx=canvas.getContext('2d'); ctx.drawImage(image,x,y,width,height,0,0,width,height);
$(document.body).append(canvas);

将 canvas 加入文档流之后,就可以看到裁剪后的效果了。不过我们还需要将图片上传至服务器里。

第五步:读取裁剪后的图片并上传

这时我们要获取 canvas 中图片的信息,用 toDataURL 就可以转换成上面用到的 DataURL 。 然后取出其中 base64 信息,再用 window.atob 转换成由二进制字符串。但 window.atob 转换后的结果仍然是字符串,直接给 Blob 还是会出错。所以又要用 Uint8Array 转换一下。总之这里挺麻烦的。。

var data=canvas.toDataURL();

// dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
data=data.split(',')[1];
data=window.atob(data);
var ia = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i);
}; // canvas.toDataURL 返回的默认格式就是 image/png
var blob=new Blob([ia], {type:"image/png"});

这时候裁剪后的文件就储存在 blob 里了,我们可以把它当作是普通文件一样,加入到 FormData 里,并上传至服务器了。

FormData 顾名思义,就是用来创建表单数据的,用 append 以键值的形式将数据加入进去即可。但他最大的特点就是可以手工添加文件或者 Blob 类型的数据,Blob 数据也会被当作文件来处理。原生 js 可以直接传递给 xhr.send(fd), jquery 可以放入 data 里请求。

全选复制放进笔记
var fd=new FormData();

fd.append('file',blob);
$.ajax({
url:"your.server.com",
type:"POST",
data:fd,
success:function(){}
});

然后你服务器里应该就可以收到这个文件了~

HTML5 本地裁剪上传图片的更多相关文章

  1. HTML5 本地裁剪图片

    下面奉上我自己写的一个demo,代码写得比较少,很多细节不会处理.如果有不得当的地方恳请指教,谢谢啦 ^_^ ^_^   功能实现步奏:   一:获取文件,读取文件并生成url   二:根据容器的大小 ...

  2. HTML5 本地裁剪图片并上传至服务器(转)

    很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的.但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 ...

  3. LocalResizeIMG前端HTML5本地压缩图片上传,兼容移动设备IOS,android

    LocalResizeIMG前端HTML5本地压缩图片上传,兼容移动设备IOS,android jincon 发表于 2015-02-26 18:31:01 发表在: php开发 localresiz ...

  4. <<< html5本地储存

    类似与Cookies,但由于Cookies储存量太小,大小也只有4-5KB的样子,html5的本地储存能存5M大小的数据 html5本地储存属性有,localStorage和sessionStorag ...

  5. HTML5本地存储——IndexedDB(一:基本使用)

    在HTML5本地存储——Web SQL Database提到过Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了 Web Storage(Local Stora ...

  6. HTML5本地数据库(SQLite)示例

    本文转载自http://blog.sina.com.cn/s/blog_641cf27f01016pm5.html 按照国内一HTML5先行者的例子仿写了一个用HTML5 API来操作本地SQLite ...

  7. HTML5本地缓存数据

    //HTML5本地缓存数据 function putObj(key, data) { if (!!window.localStorage) { var obj = { "key": ...

  8. HTML5本地存储——Web SQL Database

    在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数据就 ...

  9. HTML5本地存储——IndexedDB(二:索引)

    在HTML5本地存储——IndexedDB(一:基本使用)中介绍了关于IndexedDB的基本使用方法,很不过瘾,这篇我们来看看indexedDB的杀器——索引. 熟悉数据库的同学都知道索引的一个好处 ...

随机推荐

  1. HCDA day1

    OSI有几层: OSI将计算机网络体系结构(architecture)划分为以下七层: 图1.OSI模型 物理层: 将数据转换为可通过物理介质传送的电子信号 相当于邮局中的搬运工人. 物理层(Phys ...

  2. JQuery传值,接收PrintWriter的int接收不了

    <servlet>中的代码 <JSP中的代码> 很苦恼,我想要,<servlet>中传入的(0),在<jsp>中接收到这个参数,然后进行判断,从而达到判 ...

  3. centos 安装 telnet

    (转)centos7安装telnet服务 场景:在进行Telnet测试时候,发现无法连接,所以还得把这个软件也安装了 1 CentOS7.0 telnet-server 启动的问题 解决方法:   先 ...

  4. 调试日志——基于stm32的智能声光报警器(二)

    今天调试了音频部分的播放功能,这里我采用的是输出pwm来播放声音的方式. 声音的源文件是一个wav文件,然后用一个软件将wav文件转化为一个数组的文件. 要播放的文件就是这个数组文件里面的数据部分,前 ...

  5. 20155334 2016-2017-2 《Java程序设计》第四周学习总结

    20155334 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 第六章:继承与多态 继承:面对对象中,子类继承父类,避免重复的行为定义 extends表示会 ...

  6. Dlib简介及在windows7 vs2013编译过程

    Dlib是一个C++库,包含了许多机器学习算法.它是跨平台的,可以应用在Windows.Linux.Mac.embedded devices.mobile phones等.它的License是Boos ...

  7. day5 页面布局

    1.主站 <div class='pg-header'> <div style='width:980px;margin:0 auto;'> 内容自动居中 </div> ...

  8. 【LG3236】[HNOI2014]画框

    [LG3236][HNOI2014]画框 题面 洛谷 题解 和这题一模一样. 将最小生成树换成\(KM\)即可. 关于复杂度,因为决策点肯定在凸包上,且\(n\)凸包的期望点数为\(\sqrt {\l ...

  9. DE1-SOC开发板使用学习

    1. Yocto build utility 工具是什么?Linux Console with framebuffer是什么? 2. 文档里面有几个Linux发布版本的,分别是ubuntu和LXDE版 ...

  10. 存一下emacs配置

    (global-set-key [f9] 'compile-file)(global-set-key [f10] 'gud-gdb)(global-set-key (kbd "C-z&quo ...