webAPP如何实现移动端拍照上传(Vue组件示例)?
摘要:使用HTML5编写移动Web应用,主要是为了尝试一下“一套代码多处运行
”,一个webapp几乎可以不加修改的运行在PC/Android/iOS等上面运行。但是写到现在觉得虽然这种方式弊大于利,不仅在速度上有差异,webapp对移动端的一些原生功能支持并没有那么好。我用的vue写的系统,完成之后用webpack打包模块,hbuilder打包成apk,但是要解决的问题并不少。现在来说说webapp拍照上传。
html5是支持拍照上传或者调用本地相册的,
- <!--兼容安卓微信调用摄像头-->
- <input type="file" name="file" capture="camera">
- <!--兼容安卓默认选择sd卡上的相册图片-->
- <input type="file" name="file" accept="image/*" >
然而hbuilder打包apk之后,在安卓机(华为荣耀9)测试的时候,发现 capture="camera" 失效了,打开的是本地相册,但是不能调用摄像头。我就打开了webpack-server,移动端的浏览器运行的时候,在浏览器里面是可以调用摄像头的,最后发现了很多人都有这个问题,但是并没有说明解决办法。我自己最后是结合H5提供的 window.plus 功能调用移动端的摄像头,当然,先判断移动端是否支持 window.plus ,如果不支持,就依然用 <input> 实现图片选取。
H5 的 plus.camera 官方 API:http://www.html5plus.org/doc/zh_cn/camera.html
下面我就说说我的解决方法,主要是参照了网上一些实例和官网API写出来的,请看下面的VUE组件,这个组件可以直接引用,有兴趣的同学可以试试:
- <template>
- <div>
- <div class="camera-photo" ref="divGenres" v-show="isPhoto" @click="choiceImg">
- <img style="width:300px;height:300px;" src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1528077222&di=69a2ffcffd12e35216ab71da7a610abe&src=http://img.zcool.cn/community/01f15555b4df7e6ac725ca50c172a1.png@2o.png"/>
- <br>
- <span>请选择图片上传</span>
- <input type="file" ref="uploadImage" @change="onFileChange" accept="image/*" capture="camera" style="display: none;">
- </div>
- <div class="list-li" v-show="show">
- <div style="display: inline-block;">
- <a class="list-link" @click='previewImage(imgsrc)'>
- <img :src="imgsrc">
- </a>
- <span class="list-img-close" @click='delImage'></span>
- </div>
- <div class="add-preview" v-show="isPreview" @click="closePreview">
- <img :src="previewImg">
- </div>
- <button type="button" class="upload-button" @click="upload">图片上传</button>
- </div>
- </div>
- </template>
- <script>
- import Bus from '../bus.js'
- import qs from "qs"
- export default {
- data(){
- return{
- imgsrc:'',//上传的·图片的地址
- show:false,//图片放大预览
- previewImg: '',//预览图片的地址
- isPreview: false,//是否预览当前图片
- isPhoto: true,
- uploadFile:null
- }
- },
- methods:{
- choiceImg(){
- let self = this;
- if (!window.plus){
- self.addPic()//如果不支持plus,就用本地相册上传即可
- return;
- }
- let title = "选择照片"
- let btns = ['拍照','相册']
- var func = function(e){
- var index = e.index;
- if(index == 1) self.choiceCamera();
- if(index == 2) self.choicePic();
- }
- if(title && btns && btns.length > 0){
- var btnArray = [];
- for(var i=0; i<btns.length; i++){
- btnArray.push({title:btns[i]});
- }
- plus.nativeUI.actionSheet({
- title : title,
- cancel : '取消',
- buttons : btnArray
- }, function(e){
- if(func) func(e);
- });
- }
- },
- choiceCamera(){
- let self = this;
- var cmr = plus.camera.getCamera();
- cmr.captureImage(function (path){
- plus.io.resolveLocalFileSystemURL(path, function(entry){
- self.imgsrc= entry.toLocalURL();
- self.show = true;
- }, function(e){plus.nativeUI.toast("读取拍照文件错误:" + e.message); });
- }, function(e){},{index:1,filename:"_doc/camera/"});
- } ,
- choicePic(){
- let self = this;
- plus.gallery.pick( function(p){
- plus.io.resolveLocalFileSystemURL(p, function(entry) {
- self.imgsrc= entry.toLocalURL();
- self.show = true;
- }, function(e) {
- plus.nativeUI.toast("读取拍照文件错误:" + e.message);
- });
- }, function ( e ) { plus.nativeUI.toast("读取拍照文件错误:" + e.message);}, {
- filename: "_doc/camera/",
- filter:"image"
- } );
- },
- upload(){
- var self = this
- var wt ;
- if (window.plus)
- wt = plus.nativeUI.showWaiting();
- var img = new Image,
- width = 512, //image resize 压缩后的宽
- quality = 0.5, //image quality 压缩质量
- canvas = document.createElement("canvas"),
- drawer = canvas.getContext("2d");
- img.src = self.imgsrc;
- img.onload = function(){//利用canvas压缩图片
- canvas.width = width;
- canvas.height = width * (img.height / img.width);
- drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
- var base64 = canvas.toDataURL("image/*", quality);
- var pic = base64.split(',')[1];//图片的base64编码内容
- var f=self.imgsrc;
- var filename=f.replace(f.substring(0, f.lastIndexOf('/') + 1), '');//图片名称
- if(self.uploadFile !== null){//addPic方法得到的图片文件
- filename = self.uploadFile.name
- let reader = new FileReader();
- reader.readAsDataURL(self.uploadFile);
- reader.onload = function(e){
- img.src = e.target.result;
- }
- img.onload = function(){
- canvas.width = width;
- canvas.height = width * (img.height / img.width);
- drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
- base64 = canvas.toDataURL("image/*", quality);
- pic = base64.split(',')[1];
- }
- }
//此处是将图片上传到服务器的代码,略过- }
- },
- onFileChange(e){
- let self = this;
- let files = e.target.files || e.dataTransfer.files;
- if (!files.length) return;
- let file = files[0];//File对象
- self.uploadFile = file;
- let reader = new FileReader();//FileReader对象
- reader.readAsDataURL(file);//该方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
- reader.onload = function(e){
- self.imgsrc= e.target.result;//图片内容的base64编码
- self.show = true;
- }
- },
- addPic: function (e) {
- let els = this.$refs.divGenres.querySelectorAll('input[type=file]')
- els[0].click()
- return false
- },
- delImage: function () {
- this.imgsrc = "";
- this.show = false;
- this.isPreview = false;
- },
- previewImage: function (url) {
- let vm = this;
- vm.isPreview = true;
- vm.previewImg = url;
- },
- closePreview: function () {
- let vm = this;
- vm.isPreview = false;
- vm.previewImg = "";
- },
- },
- }
- </script>
- <style>
- .upload-button{
- display: block;
- margin-top: 10px;
- }
- .camera-photo{
- text-align:center;
- margin-top:80px;
- }
- .list-li {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 8px;
- margin-top:10px;
- position: relative;
- text-align: center;
- margin-left: auto;
- margin-right: auto;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- }
- .list-link img {
- width: 150px;
- height: 150px;
- }
- .list-link a:visited {
- background-color: #465c71;
- border: 1px #4e667d solid;
- color: #dde4ec;
- display: flex;
- line-height: 1.35em;
- padding: 4px 20px;
- text-decoration: none;
- white-space: nowrap;
- overflow: hidden;
- }
- .list-link a:hover {
- background-color: #bfcbd6;
- color: #465c71;/
- text-decoration: none;
- }
- .list-link a:active {
- background-color: #465c71;
- color: #cfdbe6;
- text-decoration: none;
- }
- .list-img-close {
- background: #ffffff url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1526905315674&di=4c2d6a6985b34e141f37bc9fae7f2209&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F15%2F55%2F73%2F39I58PICCqK_1024.png) no-repeat right top;
- border-color: #ff4a00;
- background-position: center;
- background-size: 35px 35px;
- display: block;
- float: left;
- top: 5px;
- width: 10px;
- height: 10px;
- position: absolute;
- margin-top: 0px;
- margin-left: 135px;
- padding: 8px;
- z-index: 10;
- border-radius: 5px;
- text-align: center;
- }
- .add-preview{
- width: 300px;
- height: 300px;
- }
- .add-preview img{
- width: 100%;
- height: 100%;
- }
- </style>
总之,尝试之后觉得,web工程师如果要做移动端开发,还是得有安卓或者ios工程师的支持。
补充:2018-8-24
canvas的图片压缩原理,canvas可以改变图片大小,也可以改变图片质量。quality改变图片质量。base64只是对图片对应的二进制码,按照六位对应一个字符规则做转换,转码后是反而比原图片文件大的。但是对于小图片而言,经转换后多出来的字节传输远比多建立一个http连接开销小,所以会利用base64对小图转码来提高页面加载速度。至于图片压缩原理,简单来说,通过算法减少一张图片上的颜色差异,牺牲图片画质。比如紧挨着的颜色相近的四个像素的颜色信息压缩前大概占16个字节,压缩后变成一个颜色就能减少近4倍。quality用来控制色差的力度,值越小力度越大,颜色相差较大的两个像素也会被处理,自然被压缩后文件就越小,画质就越烂。
用base64编码,源文件会变大,base64不能压缩图片,base64就是为了减少http请求。
webAPP如何实现移动端拍照上传(Vue组件示例)?的更多相关文章
- 附件上传vue组件封装(一)
//父页面部分 <attachment @newFileList="newFileList" :operationType="operationType" ...
- iOS拍照上传后,在web端显示旋转 Swift+OC版解决方案
问题描述: 手机头像上传,遇到一个怪现象,就是拍照上传时,手机端显示头像正常,但在web端查看会有一个左旋90度的问题. 并且照片竖怕才会有此问题,横拍不存在. 原因分析: 手机拍照时,用相机拍摄出来 ...
- Android4.4 + WebAPI 实现拍照上传
网上有很多关于拍照上传的实现方法,如果用新版本android去运行有可能会发现根本实现不了.主要原因是android从4.4版本开始通过intent.ACTION_GET_CONTENT打开选择器后, ...
- php实现手机拍照上传头像功能
现在手机拍照很火,那么如何使用手机拍照并上传头像呢?原因很简单,就是数据传递,首先手机传递照片信息,这个就不是post传递 也不是get函数传递, 这个另外一种数据格式传递,使用的是$GLOBALS ...
- php实现视频拍照上传头像功能实例代码
如果要在php中实现视频拍照我们需要借助于flash插件了,由flash拍出的确照片我们再通过php的$GLOBALS ['HTTP_RAW_POST_DATA']接受数据,然后保存成图片就可以了,下 ...
- 移动端图片上传解决方案localResizeIMG先压缩后ajax无刷新上传
现在科技太发达,移动设备像素越来越高,随便一张照片2M+,但是要做移动端图片上传和pc上略有不同,移动端你不能去限制图片大小,让用户先处理图片再上传,这样不现实.所以理解的解决方案就是在上传先进行图片 ...
- html5调用手机摄像头,实现拍照上传功能
今天做手机网站,想实现手机扫描二维码功能.首先实现在浏览器中调用手机摄像头,实现拍照功能并且把拍下的照片显示在页面并上传到服务器上,然后再在服务器端进行分析. 首先实现在浏览器中调用摄像头,当然用现在 ...
- 【Demo】HTML5 拍照上传
本文主要讲解 手机浏览器 如何拍照 为什么会有这个需求 最近做一个项目要用到拍照然后上传照片,但是网页拍照一般都是用Flash做的,而我们主要是H5页面,如果在微信里面有权限就可以通过JSSDK调起摄 ...
- Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...
随机推荐
- 在过去五分钟内,TypeScript语言服务以外终止了5次
这个问题困扰了我两次...第一次重装了VS CODE 具体的原意找到之后我直接想骂娘....... 各位如果碰到这个问题....请打开你的360安全卫士!!! 注意看看您家360的防护日志有木有贴心帮 ...
- bottle模板中的替换
line是模板中一行的内容,类似: {{x}}testinfo{{x+10}} x=10时,模板输出: 10testinfo20 x = 10 splits = re.split(r'\{\{(.*? ...
- 牛客网小a的旅行计划
地址:https://ac.nowcoder.com/acm/contest/223/B 此题是一道套公式题目,不难,ans=(pow(4,n+1)-4*pow(3,n+1)+6*pow(2,n+1) ...
- vue添加页面键盘事件
我司开发项目,用的是vue+elementUI,做登陆页面的时候,点击enter键的时候要实现和点击登陆按钮一样的功能,所以就百度了一下,于是一通百度之后,就在点击按钮上面直接添加了@keyup.en ...
- 分频器的Verilog实现
一.占空比50%的奇数分频 1.实现思路 实现奇数(N)分频,分别用上升沿计数到(N-1)/2,再计数到N-1:用下降沿计数到(N-1)/2,再计数到N-1,得到两个波形,然后把它们相或即可得到N分频 ...
- python学习第四次笔记
python学习第四次记录 列表list 列表可以存储不同数据类型,而且可以存储大量数据,python的限制是 536870912 个元素,64位python的限制是 1152921504606846 ...
- java编码与解码(一)
转:https://blog.csdn.net/heyanxi0101/article/details/80356870 java编码与解码(一) 编码表概述和常见的编码表 概述:有字符及其对应的数值 ...
- 微信小程序页面跳转,带参数跳转
1. wx.navigateTo (保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面.) 路径:只能跳转非tabbar路径 参数: 'path?key=v ...
- SQL注入之Sqli-labs系列第五十关,第五十一关,第五十二关,第五十三关(ORDER BY堆叠注入)
0x1第五十关 源码中使用的mysqli_multi_query()函数,而之前使用的是mysqli_query(),区别在于mysqli_multi_query()可以执行多个sql语句,而mysq ...
- 查询MySQL数据库中表结构的几种方法
什么是表结构?表结构就是定义数据表文件名,确定数据表包含哪些字段,各字段的字段名.字段类型.及宽度,并将这些数据输入到计算机当中. 查询方法:以表‘employees’为例子 1.describe(d ...