背景:

本人的一个移动端H5项目,需求如下:

  需求一:手机相册选取或拍摄照片后在页面上预览

  需求二:然后绘制在canvas画布上

这里,我们先看一个demo(http://jsfiddle.net/q3011893/83qfqpk8/embedded/

  需求一:drawTempPhoto方法

  需求二:drawPhoto方法

操作步骤:

1、点击选择文件,拍摄一张照片,此时"预览:"文字下会显示你刚才拍摄的照片;

2、再点击"draw on Canvas",该按钮下的画布会绘制你刚才拍摄的照片。

正常的结果:

--------------------------------------------------------------------------------------------------------

正文:

1、让input file支持拍照+相册选取
 
    1. <input accept="image/*" type="file" id="file" />
    2. //有一些特殊的安卓机还需要加上 capture="camera" 属性才能支持拍照

2、需求一的预览功能使用html5提供的新API:FileReader

介绍:

FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。

API文档:

https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

兼容性:

主流浏览器都支持。除了IE有点问题,详情看下图:

使用方法(使用drawTempPhoto方法实现需求一):

  1. //绘制照片
  2. function drawTempPhoto() {
  3.  
  4.     //检验是否为图像文件
  5.     var file = document.getElementById("file").files[0];
  6.     if (!/image\/\w+/.test(file.type)) {
  7.         alert("看清楚哦,这个需要图片!");
  8.         return false;
  9.     }
  10.     var reader = new FileReader();
  11.     //将文件以Data URL形式读入页面
  12.     reader.readAsDataURL(file);
  13.     reader.onload = function (e) {
  14.  
  15.         //预览效果
  16.         var img = $("#photo")[0];
  17.         //加载图片,此处的this.result为base64格式
  18.         img.src = this.result;
  19.  
  20.     }
  21.  
  22. }

  注:

  

  在本人的三星note5的手机中,需求一会出现照片预览逆时针旋转90度的bug(其实用下面介绍的的exif.js方法,可以知道iOS和三星所拍的照片Orientation值都是6,而前者做了预览的修正,后者则直接显示了出来,导致了旋转)。

   解决方案:

   判断是否为三星手机设备,然后把预览的图片顺时针旋转90度恢复正常(例如可以用canvas技术模拟预览效果)。

  于是修改的drawTempPhoto方法如下【line:21-27】:

  1. //绘制照片
  2.     function drawTempPhoto() {
  3.  
  4.         //检验是否为图像文件
  5.         var file = document.getElementById("file").files[0];
  6.         if (!/image\/\w+/.test(file.type)) {
  7.             alert("看清楚哦,这个需要图片!");
  8.             return false;
  9.         }
  10.         var reader = new FileReader();
  11.         //将文件以Data URL形式读入页面
  12.         reader.readAsDataURL(file);
  13.         reader.onload = function (e) {
  14.  
  15.             //预览效果
  16.             var img = $("#photo")[0];
  17.             //加载图片,此处的this.result为base64格式
  18.             img.src = this.result;
  19.             img.onload = function(){
  20.  
  21.                 //获取照片的拍摄方向
  22.                 var orient = getPhotoOrientation(img);
  23.                 alert("orient1:" + orient);
  24.                 //判断是否是三星手机
  25.             // if (isSamsung) {
  26.                       // 做旋转的适配……
  27.                 // }
  28.  
  29.             };
  30.  
  31.         }
  32.  
  33.     }
3、需求二绘制到Canvas,使用exif.js解决iOS(包括三星note5)等一些手机照片旋转90度的bug

  在iOS上,表现如下:

  可见,在iOS上第一张图正常,而第二张图逆时针旋转了90度,而其他的安卓两步都是正常的显示。

  那我们来看看exif.js是什么?

  介绍:

  Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。

  兼容性:

  EXIF 数据主要来自拍摄的照片,多用于移动端开发,PC 端也会用到,此插件兼容主流浏览器,IE10 以下不支持。

  下载地址:

https://github.com/exif-js/exif-js

  这里我们知道了exif.js其实是获取一张拍摄照片的元信息的,进而获取它最初的拍照方向,这很可能跟iOS图片旋转的bug有关。

  而exif.js提供的一张照片的Orientation属性如下:

  

  解决方案:

  1、我首先引入exif.js:

  1.   <script src="./js/exif.js"></script>

 

  2、然后封装成getPhotoOrientation方法:

  1. //获取照片的元信息(拍摄方向)
  2. function getPhotoOrientation(img){
  3.     var orient;
  4.     EXIF.getData(img, function () {
  5.         orient = EXIF.getTag(this, 'Orientation');
  6.     });
  7.     return orient;
  8. }

  3、分别在操作步骤一选择图片和操作步骤二draw on Canvas,Alert照片的Orientation值,本人的测试机有限,请见谅,结果如下:

手机型号

Orientation值

iphone 6S

小米4S

undefined

华为荣耀4A

1

PC

undefined

  可以看到,小米4S和PC都是undefined,表示图片没有拍摄方向或者根本没记录,华为荣耀4A是1,表示的是正确的方向,以上都没问题。但iphone 6S为6!所以之所以出现了图片的旋转,是因为它本身的Orientation就不正常!!

  因此解决这个bug的思路是:获取到照片拍摄的方向,对ios照片进行角度旋转修正。

  修改后的demo(http://jsfiddle.net/q3011893/k3z5ev26/embedded/

  除了上面引入的exif.js和添加的getPhotoOrientation方法,我又修改了drawPhoto方法:

  ①旧drawPhoto方法:

  1. //绘制照片
  2. function drawPhoto(photo, x, y, w, h) {
  3.  
  4.     var canvas = document.getElementById("canvas");
  5.     if (canvas.getContext) {
  6.         var ctx = canvas.getContext("2d");
  7.  
  8.         //draw on Canvas
  9.         var img = new Image();
  10.         img.onload = function () {
  11.  
  12.             var canvas_w = Number(ctx.canvas.width);
  13.             var canvas_h = Number(ctx.canvas.height);
  14.  
  15.             // 执行Canvas的drawImage语句
  16.             ctx.drawImage(img, x, y, w, h);
  17.  
  18.         }
  19.         img.src = photo.src; // 设置图片源地址
  20.     }
  21. }

  ②新drawPhoto方法【line:4-6,19-30】:

  1. //绘制照片
  2. function drawPhoto(photo, x, y, w, h) {
  3.  
  4.     //获取照片的拍摄方向
  5.     var orient = getPhotoOrientation(photo);
  6.     alert("orient2:"+orient);
  7.  
  8.     var canvas = document.getElementById("canvas");
  9.     if (canvas.getContext) {
  10.         var ctx = canvas.getContext("2d");
  11.  
  12.         //draw on Canvas
  13.         var img = new Image();
  14.         img.onload = function () {
  15.  
  16.             var canvas_w = Number(ctx.canvas.width);
  17.             var canvas_h = Number(ctx.canvas.height);
  18.  
  19.             //判断图片拍摄方向是否旋转了90度
  20.             if (orient == 6) {
  21.                 ctx.save();//保存状态
  22.                 ctx.translate(canvas_w / 2, canvas_h / 2);//设置画布上的(0,0)位置,也就是旋转的中心点
  23.                 ctx.rotate(90 * Math.PI / 180);//把画布旋转90度
  24.                 // 执行Canvas的drawImage语句
  25.                 ctx.drawImage(img, Number(y) - canvas_h / 2, Number(x) - canvas_w / 2, h, w);//把图片绘制在画布translate之前的中心点,
  26.                 ctx.restore();//恢复状态
  27.             } else {
  28.                 // 执行Canvas的drawImage语句
  29.                 ctx.drawImage(img, x, y, w, h);
  30.             }
  31.  
  32.         }
  33.         img.src = photo.src; // 设置图片源地址
  34.     }
  35. }

  运行结果如下:

   完美~

移动端上传照片 预览+Draw on Canvas's Demo(解决 iOS 等设备照片旋转 90 度的 bug)的更多相关文章

  1. hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images

    hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images, 本例子主要是使用HTML5 的File API,建立一個可存取到该file的url, 一个空的img标签,ID为img0,把 ...

  2. html之file标签 --- 图片上传前预览 -- FileReader

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  3. 【转】HTML5 jQuery图片上传前预览

    hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images,本例子主要是使用HTML5 的File API,建立一個可存取到该 file的url,一个空的img标签,ID为img0,把选 ...

  4. ASP.NET MVC图片上传前预览

    回老家过春节,大半个月,在家的日子里,吃好睡好,人也长了3.5Kg.没有电脑,没有网络,无需写代码,工作上相关的完全放下......开心与父母妻儿过个年,那样的生活令Insus.NET现在还在留恋.. ...

  5. Jcrop+uploadify+php实现上传头像预览裁剪

    最近由于项目需要,所以做了一个上传头像预览并且可以预览裁剪的功能,大概思路是上传的图片先保存到服务器,然后通过ajax从服务器获取到图片信息,再利用Jcrop插件进行裁剪,之后通过PHP获取到的四个裁 ...

  6. 图片上传本地预览。兼容IE7+

    基于JQUERY扩展,图片上传预览插件 目前兼容浏览器(IE 谷歌 火狐) 不支持safari 预览地址:http://www.jinbanmen.com/test/1.html js代码:/**名称 ...

  7. js上传和预览图片

    [1].[代码] [HTML]代码 跳至 [1] <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  8. DevExpress控件使用系列--ASPxUploadControl(图片上传及预览)

        1.控件功能     列表控件展示数据.弹框控件执行编辑操作.Tab控件实现多标签编辑操官方说明 2.官方示例       2.1 ASPxImage                http: ...

  9. HTML5 jQuery图片上传前预览

    hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images,本例子主要是使用HTML5 的File API,建立一個可存取到该file的url,一个空的img标签,ID为img0,把选择 ...

随机推荐

  1. hdfs 复制路径下所有文件

    hadoop fs -cp $SRC_FILE $TARGET_FILE hadoop fs -cp $SRC_DIR $TARGET_DIR 注:复制路径时,最后一个斜杠是没有的.添加斜杠后报文件找 ...

  2. webpack模块加载css文件及图片地址

    webpack支持css文件加载并打包,只需安装相应加载器并在配置文件中配置 . 加载的css文件内容会与该模块里的js内容混合封装,这样做的好处是一个js文件包含了所有的css与js内容,有效减少了 ...

  3. hadoop+tachyon+spark的zybo cluster集群综合配置

    1.zybo cluster 架构简述: 1.1 zybo cluster 包含5块zybo 开发板组成一个集群,zybo的boot文件为digilent zybo reference design提 ...

  4. 关于Delphi错误:Cannot make a visible window modal

    Delphi的fsMDIChild类型的窗体是不能使用ShowModal的,否则会弹出"Cannot make a visible window modal"异常, 但是把fsMD ...

  5. 系统吞吐量(TPS)、用户并发量、性能测试概念和公式

    分享一个概念: http://www.ha97.com/5095.html

  6. IE7中使用Jquery动态操作name问题

    问题:IE7中无法使用Jquery动态操作页面元素的name属性. 在项目中有出现问题,某些客户的机器偶尔会有,后台取不到前台的数据值. 然开发和测试环境总是不能重现问题.坑爹之处就在于此,不能重现就 ...

  7. 【转】我的技术学习方法 — Anytao

    原文作者:anytao—王涛 他的著作:<你必须知道的.Net> 关于这个问题,也有不少刚刚入行的朋友向我问起.我想可能一千个人就有一千个答案,我不能保证自己的想法适合于所有的人,但是这确 ...

  8. [LeetCode] Interleaving String - 交织的字符串

    题目如下:https://oj.leetcode.com/problems/interleaving-string/ Given s1, s2, s3, find whether s3 is form ...

  9. Unbroken(坚不可摧)——Mateusz M

    Unbroken(坚不可摧)——Mateusz M YouTube励志红人账号Mateusz M 的作品,短片由几位演讲家Les Brown.Eric Thomas.Steve Jobs.Louis ...

  10. 《Spark快速大数据分析》—— 第五章 数据读取和保存

    由于Spark是在Hadoop家族之上发展出来的,因此底层为了兼容hadoop,支持了多种的数据格式.如S3.HDFS.Cassandra.HBase,有了这些数据的组织形式,数据的来源和存储都可以多 ...