因为最近遇到个移动端上传头像的需求,上传到后台的数据是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. 远程管理 KVM 虚机

    上一节我们通过 virt-manager 在本地主机上创建并管理 KVM 虚机.其实 virt-manager 也可以管理其他宿主机上的虚机.只需要简单的将宿主机添加进来 填入宿主机的相关信息,确定即 ...

  2. 使用 ftrace 调试 Linux 内核,第 3 部分

    内核头文件 include/linux/kernel.h 中描述了 ftrace 提供的工具函数的原型,这些函数包括 trace_printk.tracing_on/tracing_off 等.本文通 ...

  3. ubuntu下不同版本python安装pip及pip的使用

    由于ubuntu系统自带python2.7(默认)和python3.4,所以不需要自己安装python. 可以使用python -V和python3 -V查看已安装python版本. 在不同版本的py ...

  4. centos升级glibc(升级到 2.17版)

    https://blog.csdn.net/wyl9527/article/details/78256066

  5. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  6. 洛谷—— P2656 采蘑菇

    https://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连 ...

  7. mysql大数据量分页查询优化

    参考文章:https://www.dexcoder.com/selfly/article/293 Mysql的分页查询十分简单,但是当数据量大的时候一般的分页就吃不消了. 传统分页查询:SELECT ...

  8. 【grpc】项目启动缺少grpc架包引用

    项目启动缺少grpc架包引用 导致 项目无法启动 解决方法: 在命令行执行 ./gradlew generateProto 下载完成之后  刷新gradle或者maven 再重启项目

  9. pyv8的安装和使用:python中执行js代码

    pyv8 的作用是在python中执行js代码,然后可以使用js里的变量等内容.python取得javascript里面的值.javascript取得python里面的值.python和javascr ...

  10. OHIFViewer meteor build 问题

    D:\Viewers-master\OHIFViewer>meteor build --directory d:/h2zViewerC:\Users\h2z\AppData\Local\.met ...