通过typescript实现一个简单版本 移动端 拍照 和预览功能
1. 需求列表
- 点击拍照唤起手机后置摄像头
- 拍照完成在页面预览照片
2. 技术实现
2.1 布局和唤起后置摄像头
唤起摄像头采用 input 里面 type=‘file’ 类型,为了调用后置摄像头,需要一些组合属性:
这段是整个拍照端核心
<input type="file" class="take-picture" id="take-event" accept="image/*,camera" capture="camera">
拍照之后的预览直接就是一个img标签,同时给一个默认展示的图片的地址,视觉效果会好一些:
<img src="picture.png" id="picture"/>
期待的效果是点击图片,唤起拍照,同时替换当前的图片,但是整个效果只能通过 input type=“file” 来实现,这个时候通过css 来达到错觉效果:如下图:
完整的布局代码:
html
<div class='pbox'>
<img src="picture.png" id="picture"/>
<input type="file" class="take-picture" id="take-event" accept="image/*,camera" capture="camera">
</div>
css
<style>
*{
margin: 0;
padding: 0;
}
img{
border: 0;
}
.pbox{
position: relative;
width: 180px;
height: 160px;
overflow: hidden;
border: 1px solid #ccc;
}
#picture{
}
.take-picture{
position:absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
opacity: 0;
}
</style>
通过绝对定位和透明度来实现 错觉的点击效果,实际上获得事件的是 input标签
2.2 监听 file 数据变化获得拍照数据
通过change 事件程序监听 file是否有返回数据,同时定义一个方法来来接受返回的数 takeEventChange
2.3 获取手机的文件照片信息
通过FileReader 对象可以读取File类型的内容,并转化为 base64 编码展示给页面img 标签src属性
2.4 图片过大对图片进行压缩处理
压缩使用canvas 的toDataURL 方法生产压缩图片,并转化为 base64 编码展示给页面img 标签src属性
完整的代码:
class takePhoto{
takeEvent:any;
minHeight:number=400; // 默认高度,大于400就压缩
callback:any;
constructor(option:any,callback:Function){
this.takeEvent=document.getElementById(option.takeEventName);
if(option.minHeight){
this.minHeight=option.minHeight;
}
this.callback=callback;
this.takeEvent.addEventListener('change',this.takeEventChange.bind(this));
}
takeEventChange(evnt:any){
// console.log(this); takePhoto
// console.log(evnt.target);
let reader = new FileReader();
reader.addEventListener('load',this.readerLoad.bind(this));
reader.readAsDataURL(evnt.target.files[0]);
}
readerLoad(evnt:any){
// console.log(evnt);
// showImg.setAttribute('src', evnt.target.result)
this.compress(evnt.target.result);
}
compress(souce:any){
let img = document.createElement('img');
img.addEventListener('load',this.imgLoad.bind(this))
img.src=souce;
}
imgLoad(evnt:any){
console.log(this);
let _this = evnt.target;
// let _this = this;
let cvs = document.createElement('canvas');
let ctx:any = cvs.getContext('2d');
//let maxH = 400;
if(_this.height> this.minHeight){
_this.width = _this.width*(this.minHeight / _this.height);
_this.height = this.minHeight;
}
cvs.width = _this.width;
cvs.height = _this.height;
ctx.clearRect(0, 0, cvs.width, cvs.height);
ctx.drawImage(_this, 0, 0, _this.width, _this.height);
//let dataUrl = cvs.toDataURL();
// showImg.setAttribute('src', dataUrl)
this.callback(cvs.toDataURL());
}
}
调用
new takePhoto({
takeEventName:'take-event',
minHeight:500
}, function (srcURL:string){
let showImg:Element|any=document.querySelector('#picture');
showImg.setAttribute('src', srcURL)
// srcURL 不但可以展示同时也是传到后段的base64的编码
},);