0. 问题描述

在项目中有个图片上传的组件(vue项目)

<inputref="input"type="file"multiple="false"accept="image/*"@change="handleChange">

在ios中点击的时候会有一个拍照的选项,但是!!!拍照的时候手机拿的方向不同,上传的图片会出现不同角度的旋转,具体现象如下:

所以我们需要将旋转了的图片再转回来!!!

具体实现思路:
1. 知道图片文件当前的旋转情况
2. 将图片文件旋转指定角度
3. 上传旋转后的文件流


1. 步骤一:获取图片文件的旋转情况

每张图片文件都有其对应的数据信息,这里我们通过第三方库exif-js来获取图片的一些信息

(1) 安装依赖

npm i exif-js -D

(2) 写一个获取图片信息的通用方法

import Exif from 'exif-js';/*** @desc 获取图片信息,使用exif.js库,具体用法请在github中搜索* @param {Object} file 上传的图片文件* @param {String} tag 需要获取的信息 例如:'Orientation'旋转信息* @return {Promise<Any>} 读取是个异步操作,返回指定的图片信息*/
export const getImageTag = (file, tag) => {if (!file) return 0;return new Promise((resolve, reject) => {/* eslint-disable func-names */// 箭头函数会修改this,所以这里不能用箭头函数Exif.getData(file, function () {const o = Exif.getTag(this, tag);resolve(o);});});
};

(3) 调用该方法获取图片的旋转信息

...
// file是表单上传时通过e.target.file获取到的文件流
const or = await getImageTag(file, 'Orientation');

(4) 总结一下不同情况下的or值

所以我们需要

  • 当or = 6时:将图片逆时针旋转90度
  • 当or = 3时:将图片顺/逆时针旋转180度
  • 当or = 8时:将图片顺时针旋转90度

安卓手机下or的值为undefiend0,安卓手机不会出现旋转情况,所以不用考虑

2. 步骤二:将图片文件旋转指定角度

通过input file选择的是个文档流我们无法处理,所以这里我们通过FileReader将文档流转为base64,然后将base64渲染到canvas上,对canvas进行旋转

(1) 将文件流转为base64格式

// 使用FileReader读取文件流,file为上传的文件流
const reader = new FileReader();
reader.readAsDataURL(file);
/* eslint-disable func-names */
// 箭头函数会改变this,所以这里不能用肩头函数
reader.onloadend = function () {// this.result就是转化后的结果const result = this.result;// 将base64添加到图片标签上const img = new Image();img.src = result;img.onload = function () {// 这里添加旋转图片的代码};
};

(2) 在img.onload中添加旋转图片

const self = this;
...
img.onload = function () {// 获取旋转后的图片const data = self.getRotateImg(img, or);// 如果上传接口不支持base64,则这里需要将base64转为文档流const f = dataURLtoFile(data);// 调用接口,上传图片
}

getRotateImg方法

/*** @desc 获取旋转后的图片* @param {Object} img 图片文件* @param {Number} or 旋转信息*/
getRotateImg(img, or) {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 图片原始大小const width = img.width;const height = img.height;canvas.width = width;canvas.height = height;ctx.drawImage(img, 0, 0, width, height);switch (or) {case 6: // 顺时针旋转90度rotateImg(img, 'right', canvas);break;case 8: // 逆时针旋转90度rotateImg(img, 'left', canvas);break;case 3: // 顺时针旋转180度rotateImg(img, 'right', canvas, 2);break;default:break;}
}
..../*** @desc 旋转canvas,会对源数据canvas进行修改* @param {Object} img 图片文件* @param {String} dir 方向 left逆时针|right顺时针* @param {Object} canvas 画布* @param {Number} s 向指定方向旋转几步,1步为90度*/
export const rotateImg = (img, dir = 'right', canvas, s = 1) => {const MIN_STEP = 0;const MAX_STEP = 3;const width = canvas.width || img.width;const height = canvas.height || img.height;let step = 0;if (dir === 'right') {step += s;step > MAX_STEP && (step = MIN_STEP);} else {step -= s;step < MIN_STEP && (step = MAX_STEP);}const degree = step * 90 * Math.PI / 180;const ctx = canvas.getContext('2d');switch (step) {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;default:canvas.width = width;canvas.height = height;ctx.drawImage(img, 0, 0, width, height);break;}
};

base64转文件流方法

/*** @desc 将base64的图片转为文件流* @param {String} dataUrl base64数据* @return {Object} 文件流*/
export const dataURLtoFile = (dataUrl) => {const filename = `img${Date.now()}`;const arr = dataUrl.split(',');const mime = arr[0].match(/:(.*?);/)[1];const bstr = atob(arr[1]);let n = bstr.length;const u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new File([u8arr], filename, { type: mime });
};

3. 步骤三:上传

调用自己项目中的post方法


完整的代码放到github上,可以访问以下地址查看
https://github.com/yywang95/h5ImageUploader

移动端h5页面拍照上传图片的时候图片旋转问题相关推荐

  1. H5页面拍照上传图片步骤

    H5页面拍照上传图片步骤: 1,给相应的input标签添加监听 document.getElementById('imgCream').addEventListener('change', funct ...

  2. 【通用CSS模板】移动端H5页面统一样式.css

    /*移动端H5页面统一样式----------------------------------------*/ @charset "UTF-8"; body, html, li, ...

  3. 移动端H5页面高清多屏适配方案

    背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...

  4. 教你如何用 lib-flexible 实现移动端H5页面适配

    前话 好久没写教程了(可能会误导新手的菜鸟教程( ̄▽ ̄)"). 这是我的github,欢迎前端大大们和我一起学习交流 https://github.com/pwcong 最近入职公司做前端实 ...

  5. php清除h5格式,移动端H5页面端怎样除去input输入框的默认样式

    这次给大家带来移动端H5页面端怎样除去input输入框的默认样式,移动端H5页面端除去input输入框的默认样式的注意事项有哪些,下面就是实战案例,一起来看一下. 前两天在开发在微信访问的HTML5页 ...

  6. html5首页图标怎么除掉,移动端H5页面端如何除去input输入框的默认样式

    移动端H5页面端如何除去input输入框的默认样式 发布时间:2020-09-29 16:41:58 来源:亿速云 阅读:124 作者:小新 这篇文章主要介绍了移动端H5页面端如何除去input输入框 ...

  7. m3u8 video ios h5_移动端H5页面踩坑记

    移动端H5页面踩坑记 移动端的样式问题 「1. 安卓 font-weight:700;以上才被认为是加粗.」 「2. border 在 1px 以内是不被安卓识别的一些 0.5px 的下划线怎么搞?」 ...

  8. 移动端H5页面编辑器开发实战--原理结构篇

    一.前言 在去年10月份左右,接到了需求:开发一个H5移动端页面编辑器的任务,目的主要是解放公司内在制作这类网页的所投入的人力以及解决使用外部H5编辑器所涉及到的版权问题. 因此,一款能够与市面上已经 ...

  9. h5页面生成图片分享到微信js_微信端h5页面如何调用分享页面的接口

    这次给大家带来微信端h5页面如何调用分享页面的接口,微信端h5页面调用分享页面接口的注意事项有哪些,下面就是实战案例,一起来看一下. 最近公司做了一个给学生投票的H5页面,主要是在微信端使用,需要添加 ...

最新文章

  1. 英语阅读推荐:使用AJAX+WF+LINQ制作Google IG式首页
  2. 安装Fedora 15后需做的25件事情(转51cto)
  3. cat命令分析_学习记录
  4. 工厂模式-CaffeNet训练
  5. 一文看懂集群、分布式与负载均衡的关系
  6. 面试项目 java-服务端 18h58
  7. linux部署tomcat项目404_Tomcat部署项目的几种常见方式
  8. jquery对下拉框的操作
  9. 14012.petalinux小知识点
  10. spring 集成 spring cloud config 的相关知识
  11. python在多边形内随机生成点_Python随机生成均匀分布在三角形内或者任意多边形内的点...
  12. proteus微型计算机梯形波,接口芯片dac0832的应用 三角波、梯形波两种波形.doc
  13. mysql 日期表:工作日、周末、节假日,星期
  14. 华为云空间 微信聊天记录_微信聊天记录云同步!用了这个方法,再也不怕聊天记录丢失...
  15. 怎么把pdf文件转换成word免费转换器
  16. 计算机与机械专业 有什么大学排名,2017机械排名211大学排名
  17. 计算机黑屏启动超慢,电脑开机很慢然后黑屏连不上网怎么办(新手可学的4种简单处理方法)...
  18. Rosalind第10题——ros_bio10_CONS
  19. 网上跨行转账将实时生效 第三方支付前景渺茫
  20. 在dos中分析线程死锁堆栈消息的案例----用Thread简单Demo,教会你如何分析堆栈消息

热门文章

  1. 如何检测视频中的绿屏、绿帧问题
  2. 2.串口通信的基本概念
  3. 【面试复盘】Momenta视觉算法实习生一面
  4. uniapp 开发小程序背景音乐动画
  5. Vue01 vue基础、mvvm、ES6z知识点、计算属性、生命周期
  6. python sqlite3 fetchall_使用python sqlite3的fetchall无法显示结果?
  7. 上班族和学生族必备的在线黑科技工具网站
  8. 微带线与带状线的初步了解
  9. Ubuntu命令卸载软件
  10. 保存网页中的css和js文件,网站保存,复制网站不可复制的文字,网站抠图