JavaScript如何处理移动端拍摄图片旋转问题


Posted in Javascript onNovember 16, 2019

本文实例为大家分享了js移动端拍摄图片旋转的具体代码,供大家参考,具体内容如下

第一步:引入exif-js

<script src="https://cdn.jsdelivr.net/npm/exif-js@2.3.0/exif.min.js"></script>

第二步:

/**
 * 处理图片文件(处理移动端拍摄图片旋转问题)
 * fileObj.file 图片文件独享
 * fileObj.resolution 在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。
 * fileObj.fileType 输入的文件类型,1 file对象,2 blob对象,3 base64字符串
 * fileObj.fileName 输出的文件名称,默认为picture.jpeg
 * fileObj.callback 回调函数
 */
function handleImageFile(fileObj) {
  // 给参数附初始值
  fileObj.fileName = fileObj.hasOwnProperty("fileName") ? "images/" + fileObj.fileName : "images/picture.jpeg";
  // 获取文件类型
  var fType = fileObj.file.type;
  if (fType.indexOf("image") === -1) return fileObj.callback({
    status: 500,
    message: "文件类型不正确",
    data: null
  });
  if (!EXIF) return fileObj.callback({
    status: 500,
    message: "EXIF 不存在",
    data: null
  });
  if (fileObj.file) {
    // 获取照片方向角属性,用户旋转控制
    EXIF.getData(fileObj.file, function () {
      var orientation = EXIF.getTag(this, 'Orientation');
      var oReader = new FileReader();
      oReader.onload = function (e) {
        var image = new Image();
        image.src = e.target.result;
        image.onload = function () {
          var canvas = document.createElement("canvas");
          var ctx = canvas.getContext("2d");
          var resultFile = null;
          var ua = navigator.userAgent;
          canvas.width = this.naturalWidth;
          canvas.height = this.naturalHeight;
          ctx.drawImage(this, 0, 0, this.naturalWidth, this.naturalHeight);
          // android终端
          var isAdr = ua.indexOf("Android") > -1 || ua.indexOf("Adr") > -1;
          // ios终端
          var isIOS = ua.indexOf("iPhone") > -1 || ua.indexOf("iOS") > -1;
          // 修复ios 或 Android
          if (isIOS || isAdr) {
            // 如果方向角不为1,都需要进行旋转
            if (orientation && orientation !== "" && orientation !== 1) {
              switch (orientation) {
                case 6: // 需要顺时针(向左)90度旋转
                  rotateImg(this, "left", canvas);
                  break;
                case 8: // 需要逆时针(向右)90度旋转
                  rotateImg(this, "right90", canvas);
                  break;
                case 3: // 需要180度旋转,转两次
                  rotateImg(this, "right180", canvas);
                  break;
              }
            }
            resultFile = canvas.toDataURL("image/jpeg", fileObj.resolution);
          } else {
            resultFile = canvas.toDataURL("image/jpeg", fileObj.resolution);
          }
          switch (fileObj.fileType) {
            case 1:
            case 2:
              fileObj.callback({
                status: 200,
                message: "success",
                data: dataURLtoFile(resultFile, fileObj.fileType, fileObj.fileName)
              });
              break;
            case 3:
              fileObj.callback({
                status: 200,
                message: "success",
                data: resultFile
              });
              break;
            default:
              break;
          }
        };
      };
      oReader.readAsDataURL(fileObj.file);
    });
  } else {
    return fileObj.callback({
      status: 500,
      message: "文件不存在",
      data: null
    });
  }
  /**
   * 旋转图片
   */
  function rotateImg(img, direction, canvas) {
    if (img === null) return;
    // 最小与最大旋转方向,图片旋转4次后回到原方向
    var minStep = 0;
    var maxStep = 3;
    // img的高度和宽度不能在img元素隐藏后获取,否则会出错
    var width = img.width;
    var height = img.height;
    var step = 2;
    if (step === null) step = minStep;
    if (direction === "right90") {
      step++;
      step > maxStep && (step = minStep);
    } else if(direction === "right180") {
      step = 2;
    } else {
      step--;
      step < minStep && (step = maxStep);
    }
    // 旋转角度以弧度值为参数
    var degree = step * 90 * Math.PI / 180;
    var ctx = canvas.getContext("2d");
    switch (step) {
      case 0:
        canvas.width = width;
        canvas.height = height;
        ctx.drawImage(img, 0, 0, width, height);
        break;
      case 1:
        canvas.width = height;
        canvas.height = width;
        ctx.rotate(degree);
        ctx.drawImage(img, 0, -height, width, height);
        break;
      case 2:
        canvas.width = width;
        canvas.height = height;
        ctx.rotate(degree);
        ctx.drawImage(img, -width, -height, width, height);
        break;
      case 3:
        canvas.width = height;
        canvas.height = width;
        ctx.rotate(degree);
        ctx.drawImage(img, -width, 0, width, height);
        break;
    }
  }
  /**
   * type:1 file对象,2 blob对象
   */
  function dataURLtoFile(dataurl, type, filename) {
    var arr = dataurl.split(',');
    var mime = arr[0].match(/:(.*?);/)[1];
    var bstr = atob(arr[1]);
    var n = bstr.length;
    var u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    if (type === 1) { // 转换成file对象
      return new File([u8arr], filename, {
        type: mime
      });
    } else { // 转换成成blob对象
      return new Blob([u8arr], {
        type: mime
      });
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js变换显示图片的实例
Apr 16 Javascript
解决Jquery load()加载GB2312页面时出现乱码的两种方案
Sep 10 Javascript
jquery特效 点击展示与隐藏全文
Dec 09 Javascript
解决jQuery上传插件Uploadify出现Http Error 302错误的方法
Dec 18 Javascript
JavaScript实现提交模式窗口后刷新父窗口数据的方法
Jun 16 Javascript
js学习总结之DOM2兼容处理this问题的解决方法
Jul 27 Javascript
Javascript 严格模式use strict详解
Sep 16 Javascript
ajax与jsonp的区别及用法
Oct 16 Javascript
vue微信分享的实现(在当前页面分享其他页面)
Apr 16 Javascript
浅谈小程序globalData的那些事儿
Nov 01 Javascript
微信小程序实现组件顶端固定或底端固定效果(不随滚动而滚动)
Apr 09 Javascript
详解如何在Canvas中添加事件的方法
Apr 17 Javascript
JS Ajax请求会话过期处理问题解决方法分析
Nov 16 #Javascript
vue中注册自定义的全局js方法
Nov 15 #Javascript
微信sdk实现禁止微信分享(使用原生php实现)
Nov 15 #Javascript
微信JSSDK实现打开摄像头拍照再将相片保存到服务器
Nov 15 #Javascript
微信小程序自定义导航栏(模板化)
Nov 15 #Javascript
在node环境下parse Smarty模板的使用示例代码
Nov 15 #Javascript
微信小程序自定义头部导航栏(组件化)
Nov 15 #Javascript
You might like
IIS下PHP的三种配置方式对比
2014/11/20 PHP
PHP实现导出带样式的Excel
2016/08/28 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
PHP与以太坊交互详解
2018/08/24 PHP
jQuery 数据缓存data(name, value)详解及实现
2010/01/04 Javascript
jquery通过扩展select控件实现支持enter或focus选择的方法
2015/11/19 Javascript
vue.js父组件使用外部对象的方法示例
2017/04/25 Javascript
详解Vue2中组件间通信的解决全方案
2017/07/28 Javascript
AngularJS 表单验证手机号的实例(非必填)
2017/11/12 Javascript
在Swiper内如何制作CSS3动画效果示例代码
2017/12/07 Javascript
jquery radio 动态控制选中失效问题的解决方法
2018/02/28 jQuery
详解Webpack + ES6 最新环境搭建与配置
2018/06/04 Javascript
微信小程序自定义可滑动日历界面
2018/12/28 Javascript
vue axios封装及API统一管理的方法
2019/04/18 Javascript
js实现星星海特效的示例
2020/09/28 Javascript
[04:53]DOTA2英雄基础教程 祈求者
2014/01/03 DOTA
[07:08]2014DOTA2西雅图国际邀请赛 小组赛7月11日TOPPLAY
2014/07/11 DOTA
Python3使用requests登录人人影视网站的方法
2016/05/11 Python
分析python动态规划的递归、非递归实现
2018/03/04 Python
python numpy格式化打印的实例
2018/05/14 Python
pandas使用apply多列生成一列数据的实例
2018/11/28 Python
Python 使用threading+Queue实现线程池示例
2019/12/21 Python
python连接mysql数据库并读取数据的实现
2020/09/25 Python
HTML5 source标签:媒介元素定义媒介资源
2018/01/29 HTML / CSS
雅诗兰黛旗下走天然植物路线的彩妆品牌:Prescriptives
2016/08/14 全球购物
缅甸网上购物:Shop.com.mm
2017/12/05 全球购物
Toppik顶丰增发纤维官网:解决头发稀疏
2017/12/30 全球购物
婚鞋、新娘鞋、礼服鞋、童鞋:Nina Shoes
2019/09/04 全球购物
2014年党员自我评价材料
2014/09/22 职场文书
2014年设计师工作总结
2014/11/25 职场文书
党员个人承诺书
2015/04/27 职场文书
浪漫婚礼主持词开场白
2015/11/24 职场文书
市场营销计划书
2019/04/24 职场文书
变长双向rnn的正确使用姿势教学
2021/05/31 Python
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL
Python爬取奶茶店数据分析哪家最好喝以及性价比
2022/09/23 Python