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仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...
随机推荐
- 2018-2019-2 《网络对抗技术》Exp4 恶意代码分析 20165326
恶意代码分析 实践目标 监控你自己系统的运行状态,看有没有可疑的程序在运行. 分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systra ...
- 新手学习之浅析一下c/c++中的指针
一.我们先来回忆一下指针的概念吧,方便下面的介绍 指针是存放地址值的变量或者常量.例如:int a=1;&a就表示指针常量(“&”表示取地址运算符,也即引用).int *b,b表示的是 ...
- Mysql 设置远程连接
一.问题分析 有时候使用数据库远程连接工具连接MySQL的时候总是连接不上,确认过账号密码正确,端口telnet端口又是通的. Navicat Premium报错如下: 1130 - Host '19 ...
- mysql远程访问1045的问题解决
mysql远程访问1045的问题解决 首先进入mysql数据库,然后输入下面两个命令 grant all privileges on *.* to 'root'@'%' identified by ' ...
- type() 和 isinstance()区别
a=111 # type() 返回数据类型 In: type(a) Out: int In: print(type(a)) Out: <class 'int'> # isinstance ...
- SQL server 的身份验证模式
windows身份验证(本机的ip地址或者localhost 或者.或者127.0.0.1) SQL Server身份验证(用户名和密码登录) 常见的错误代码18456(登录失败)和18470(账户被 ...
- 【Linux】awk指令
介绍: awk是一种可以处理数据,产生格式化报表的语言.其工作方式是读取数据文件,将每一行数据视为一条记录,没笔记录按分隔符(默认空格)分割成若干字段,输出各字段的值. 实例: [jboss@vm-k ...
- css常用选择器选择器
tap选择器 ulclass选择器 .id选择器 #后代选择器 a b子代选择器 a>b兄弟选择器 a + b 以a为参考给b加样式属性选择器 input [type="text&qu ...
- Mac os系统gdb调试器的安装与使用
Mac os系统gdb调试器的安装与使用 1.简介 Mac os下的Terminal 终端中默认情况下并没有安装gdb调试器,但是可以通过gcc编译器进行代码编译,如果出错了就需要通过gdb调试器进行 ...
- Sails -初级学习配置
新建一个命名为sails的文件夹1.安装 npm -g install sails || cnpm -g install sails 注意:安装必须是全局安装 cnpm install sails - ...