因为最近遇到个移动端上传头像的需求,上传到后台的数据是base64位,其中为了提高用户体验,把比较大的图片用canvas进行压缩之后再进行上传。在移动端调用拍照功能时,会发生图片旋转,为了解决这个问题引入了exif去判断拍照时的信息再去处理图片,这是个很好的插件。关于exif.js可以去他的GitHub上了解,这边直接npm install exif-js --save   安装,然后import一下就可以使用了。以下就是源码,可以直接使用。

  1. <template>
  2. <div>
  3. <div style="padding:20px;">
  4. <div class="show">
  5. <div class="picture" :style="'backgroundImage:url('+headerImage+')'"></div>
  6. </div>
  7. <div style="margin-top:20px;">
  8. <input type="file" id="upload" accept="image" @change="upload">
  9. <label for="upload"></label>
  10. </div>
  11. </div>
  12. </div>
  13. </template>
  14. <script>
  15. import Exif from 'exif-js'
  16. export default {
  17. data () {
  18. return {
  19. headerImage:'',picValue:''
  20. }
  21. },
  22. mounted () {
  23. },
  24. methods: {
  25. upload (e) {
  26. let files = e.target.files || e.dataTransfer.files;
  27. if (!files.length) return;
  28. this.picValue = files[0];
  29. this.imgPreview(this.picValue);
  30. },
  31. imgPreview (file) {
  32. let self = this;
  33. let Orientation;
  34. //去获取拍照时的信息,解决拍出来的照片旋转问题
  35. Exif.getData(file, function(){
  36. Orientation = Exif.getTag(this, 'Orientation');
  37. });
  38. // 看支持不支持FileReader
  39. if (!file || !window.FileReader) return;
  40. if (/^image/.test(file.type)) {
  41. // 创建一个reader
  42. let reader = new FileReader();
  43. // 将图片2将转成 base64 格式
  44. reader.readAsDataURL(file);
  45. // 读取成功后的回调
  46. reader.onloadend = function () {
  47. let result = this.result;
  48. let img = new Image();
  49. img.src = result;
  50. //判断图片是否大于100K,是就直接上传,反之压缩图片
  51. if (this.result.length <= (100 * 1024)) {
  52. self.headerImage = this.result;
  53. self.postImg();
  54. }else {
  55. img.onload = function () {
  56. let data = self.compress(img,Orientation);
  57. self.headerImage = data;
  58. self.postImg();
  59. }
  60. }
  61. }
  62. }
  63. },
  64. postImg () {
  65. //这里写接口
  66. },
  67. rotateImg (img, direction,canvas) {
  68. //最小与最大旋转方向,图片旋转4次后回到原方向
  69. const min_step = 0;
  70. const max_step = 3;
  71. if (img == null)return;
  72. //img的高度和宽度不能在img元素隐藏后获取,否则会出错
  73. let height = img.height;
  74. let width = img.width;
  75. let step = 2;
  76. if (step == null) {
  77. step = min_step;
  78. }
  79. if (direction == 'right') {
  80. step++;
  81. //旋转到原位置,即超过最大值
  82. step > max_step && (step = min_step);
  83. } else {
  84. step--;
  85. step < min_step && (step = max_step);
  86. }
  87. //旋转角度以弧度值为参数
  88. let degree = step * 90 * Math.PI / 180;
  89. let ctx = canvas.getContext('2d');
  90. switch (step) {
  91. case 0:
  92. canvas.width = width;
  93. canvas.height = height;
  94. ctx.drawImage(img, 0, 0);
  95. break;
  96. case 1:
  97. canvas.width = height;
  98. canvas.height = width;
  99. ctx.rotate(degree);
  100. ctx.drawImage(img, 0, -height);
  101. break;
  102. case 2:
  103. canvas.width = width;
  104. canvas.height = height;
  105. ctx.rotate(degree);
  106. ctx.drawImage(img, -width, -height);
  107. break;
  108. case 3:
  109. canvas.width = height;
  110. canvas.height = width;
  111. ctx.rotate(degree);
  112. ctx.drawImage(img, -width, 0);
  113. break;
  114. }
  115. },
  116. compress(img,Orientation) {
  117. let canvas = document.createElement("canvas");
  118. let ctx = canvas.getContext('2d');
  119. //瓦片canvas
  120. let tCanvas = document.createElement("canvas");
  121. let tctx = tCanvas.getContext("2d");
  122. let initSize = img.src.length;
  123. let width = img.width;
  124. let height = img.height;
  125. //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
  126. let ratio;
  127. if ((ratio = width * height / 4000000) > 1) {
  128. console.log("大于400万像素")
  129. ratio = Math.sqrt(ratio);
  130. width /= ratio;
  131. height /= ratio;
  132. } else {
  133. ratio = 1;
  134. }
  135. canvas.width = width;
  136. canvas.height = height;
  137. //        铺底色
  138. ctx.fillStyle = "#fff";
  139. ctx.fillRect(0, 0, canvas.width, canvas.height);
  140. //如果图片像素大于100万则使用瓦片绘制
  141. let count;
  142. if ((count = width * height / 1000000) > 1) {
  143. console.log("超过100W像素");
  144. count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
  145. //            计算每块瓦片的宽和高
  146. let nw = ~~(width / count);
  147. let nh = ~~(height / count);
  148. tCanvas.width = nw;
  149. tCanvas.height = nh;
  150. for (let i = 0; i < count; i++) {
  151. for (let j = 0; j < count; j++) {
  152. tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
  153. ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
  154. }
  155. }
  156. } else {
  157. ctx.drawImage(img, 0, 0, width, height);
  158. }
  159. //修复ios上传图片的时候 被旋转的问题
  160. if(Orientation != "" && Orientation != 1){
  161. switch(Orientation){
  162. case 6://需要顺时针(向左)90度旋转
  163. this.rotateImg(img,'left',canvas);
  164. break;
  165. case 8://需要逆时针(向右)90度旋转
  166. this.rotateImg(img,'right',canvas);
  167. break;
  168. case 3://需要180度旋转
  169. this.rotateImg(img,'right',canvas);//转两次
  170. this.rotateImg(img,'right',canvas);
  171. break;
  172. }
  173. }
  174. //进行最小压缩
  175. let ndata = canvas.toDataURL('image/jpeg', 0.1);
  176. console.log('压缩前:' + initSize);
  177. console.log('压缩后:' + ndata.length);
  178. console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
  179. tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
  180. return ndata;
  181. },
  182. }
  183. }
  184. </script>
  185. <style>
  186. *{
  187. margin: 0;
  188. padding: 0;
  189. }
  190. .show {
  191. width: 100px;
  192. height: 100px;
  193. overflow: hidden;
  194. position: relative;
  195. border-radius: 50%;
  196. border: 1px solid #d5d5d5;
  197. }
  198. .picture {
  199. width: 100%;
  200. height: 100%;
  201. overflow: hidden;
  202. background-position: center center;
  203. background-repeat: no-repeat;
  204. background-size: cover;
  205. }
  206. </style>

vue开发:移动端图片上传的更多相关文章

  1. 移动端图片上传解决方案localResizeIMG先压缩后ajax无刷新上传

    现在科技太发达,移动设备像素越来越高,随便一张照片2M+,但是要做移动端图片上传和pc上略有不同,移动端你不能去限制图片大小,让用户先处理图片再上传,这样不现实.所以理解的解决方案就是在上传先进行图片 ...

  2. angularJS+Ionic移动端图片上传的解决办法

    前端开发中经常会碰到图片上传的问题,网上的解决办法很多,可是有些图片上传的插件会有一些附属的插件,因此因为一个图片上传的问题可能额需要引入其他插件到项目中,久而久之项目会不伦不类,有时候插件之间也会有 ...

  3. 详细阐述Web开发中的图片上传问题

    Web开发中,图片上传是一种极其常见的功能.但是呢,每次做上传,都花费了不少时间. 一个"小功能"花费我这么多时间,真心不愉快. So,要得认真分析下原因. 1.在最初学习Java ...

  4. 微信小程序开发之多图片上传+服务端接收

    前言: 业务需求,这次需要做一个小程序同时选中三张图片一起上传到服务端,后端使用的.NET WEBAPI接收数据保存. 使用技术: 在这章中将会使用到微信小程序wx.uploadFile(Object ...

  5. vue+axios实现移动端图片上传

    在利用vue做一些H5页面时,或多或少会遇到有图片上传的操作,主要是运用html5里面的input[type=file]来实现,传递到后端的数据是以二进制的格式传递,所以上传图片的请求与普通的请求稍微 ...

  6. vue移动端图片上传压缩

    上传压缩方法 import {api} from '../../api/api.js'; import axios from 'axios'; export function imgPreview ( ...

  7. HTML5移动端图片上传模块

    上传图片的功能是极为常用的,之前做过一个移动端上传文件的功能(基于jquery的),总结梳理一下. html <div class="uploadPic clearBox"& ...

  8. 用html5文件api实现移动端图片上传&预览效果

    想要用h5在移动端实现图片上传&预览效果,首先要了解html5的文件api相关知识(所有api只列举本功能所需): 1.Blob对象  Blob表示原始二进制数据,Html5的file对象就继 ...

  9. SpringBoot + Vue前后端分离图片上传到本地并前端访问图片

    同理应该可用于其他文件 图片上传 application.yml 配置相关常量 prop: upload-folder: E:/test/ # 配置SpringMVC文件上传限制,默认1M.注意MB要 ...

  10. Js 之移动端图片上传插件mbUploadify

    一.下载 https://pan.baidu.com/s/1NEL4tkHoK4ydqdMi_hgWcw 提取码:vx7e 二.Demo示例 <div class="weui_uplo ...

随机推荐

  1. 【Tomcat】使用tomcat manager 管理和部署项目,本地部署项目到服务器

    在部署tomcat项目的时候,除了把war文件直接拷贝到tomcat的webapp目录下,还有一种方法可以浏览器中管理和部署项目,那就是使用tomcat manager. 默认情况下,tomcat m ...

  2. Security arrangements for extended USB protocol stack of a USB host system

    Security arrangements for a universal serial bus (USB) protocol stack of a USB host system are provi ...

  3. Ubuntu 安装PostgreSQL

    安装最新版: sudo apt-get install postgresql 安装完成后,默认会: (1)创建名为"postgres"的Linux用户 (2)创建名为"p ...

  4. Lighttpd 服务器的安装

    https://www.cnblogs.com/rongfengliang/articles/3503228.html

  5. 读取编码器信息Python2.7和Python3.3版本差异及解决,一次订阅多次调用callback的解决

    1. Python3.3以字节类型返回编码器信息,b'...',BUF: b'\xc3KOO\x00OO\x00OO\x00OO\x00OO\x00\x03\x00\x00\x00\x00\x99R\ ...

  6. 【Java TCP/IP Socket】构建和解析自定义协议消息(含代码)

    在传输消息时,用Java内置的方法和工具确实很用,如:对象序列化,RMI远程调用等.但有时候,针对要传输的特定类型的数据,实现自己的方法可能更简单.容易或有效.下面给出一个实现了自定义构建和解析协议消 ...

  7. IOS界面调试神器DCIntrospect

    对于使用代码来写UI的同志,使用DCIntrospect来查看元素信息调整布局,再也不用凭眼睛来估了,先来看看截图 DCIntrospect是github上的开源项目:下载源码 大概介绍下用法: DC ...

  8. lib无法访问另外lib中的头文件

    工程中app已经有设置User Header Search Paths来包含了需要的头文件,但是个别的lib依然找不到头文件.解决方法: 选择这个lib,在Build Settings中查找选项Use ...

  9. Answer&#39;s Question about pointer

    When you create a new pointer, this will be in heap until you delete it.  So what you said is sort o ...

  10. Java中的反射机制,利用反射访问私有

    利用反射,首先是Class对象的获取,之后是Method和Field对象的获取. 以Method为例,从文档中可以看到: getMethod()方法返回的是public的Method对象, 而getD ...