背景
来了来了,用户奇怪的需求又来了,是这样的,原生的文件上传,在移动设备上是可以调用摄像头现拍然后直接上传的,而web端则是弹出选择图片的窗口,而用户用的那个平板,却是后者,他想直接拍直接上传,然后我就想,把设备的照相机功能放在任务栏不就行了吗,结果他们说,操作的工人都是年龄比较大的老工人了,那么繁琐的操作他们整不明白…然后我就只能,封装个组件…
ps:需要注意的是,浏览器只支持 https,localhost和127.0.0.1调用摄像头,而http是不支持的,但是只有http怎么办呢,也是有方法可以配置的:
在浏览器地址栏中输入“chrome://flags/#unsafely-treat-insecure-origin-as-secure”,回车,如下图,将该选项置为Enabled,在输入框中输入需要访问的地址,多个地址使用“,”隔开,然后点击右下角弹出的Relaunch按钮,自动重启浏览器之后就可以在添加的http地址下调用摄像头和麦克风了。
话不多说,上代码:
HTML
<div class="cameraBox"></div>
复制
JS( 这个项目用的jquey,很久没写了,写的不好,大佬勿喷)
var canvas var video var videoWidth var videoHeight var cameraIsOpen = false // 摄像头是否开启 默认为否 $(()=>{ //这里就是一个按钮一个弹框,可以自由发挥 let cameraBoxCode = `<button type="button" class="btn btn-default" title="开启摄像头" οnclick="cameraOpen()" > <i class="fa fa-camera"></i> </button> <span id="photoName"></span> <div id='cameraModal' class="modal fade" role="dialog" tabindex="1" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header myDataTableModalHead" style="height: 3em;vertical-align: middle;padding: 5px 16px;"> <button type="button" class="close" οnclick="modalClose()" aria-label="Close"> <span aria-hidden="true"> × </span> </button> <span class="cardIcon"></span><h4 class="modal-title">拍照</h4> </div> <div class="modal-body" style="max-height:80vh;overflow:overlay"> <video id="video" width="100%" autoplay="autoplay"></video> <canvas id="canvas" width="100%"></canvas> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" οnclick="modalClose()"> <label data-locale="i18n_cancel"></label> </button> <button type="button" class="btn btn-primary" οnclick="takePhoto()"> <label>拍照</label> </button> </div> </div> </div> </div>` $('.cameraBox').append(cameraBoxCode) }) //打开摄像头弹框 function cameraOpen(){ canvas = document.getElementById('canvas') video = document.getElementById('video') $('#cameraModal').modal('show') setTimeout(()=>{ getMedia() },1000) } //调取摄像头 function getMedia(){ $('#canvas').hide() $('#video').show() videoWidth = '500' videoHeight = '500' // 摄像头宽高 navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia || navigator.mediaDevices.getUserMedia if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ video: {width:videoWidth,height:videoHeight}, audio: false }).then((stream) => { mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0] video.srcObject =stream video.play() cameraIsOpen = true }).catch((err) => { $.modal.error('调用摄像头失败,请检查设备是否连接!') }) } else if (navigator.getMedia) {// 使用旧方法打开摄像头 navigator.getMedia({ video: {width:videoWidth,height:videoHeight}, }, (stream) => { mediaStreamTrack = stream.getTracks()[0] video.srcObject =stream video.play() cameraIsOpen = true }, (err) => { $.modal.error('调用摄像头失败,请检查设备是否连接!') }) } } //拍照 function takePhoto(){ $('#canvas').attr('width',videoWidth) $('#canvas').attr('height',videoHeight) $('#video').hide() $('#canvas').show() let ctx = canvas.getContext('2d') ctx.drawImage(video,0,0,videoWidth,videoHeight) let pic = canvas.toDataURL('image/png') pic = pic.replace(/^data:image\/(png|jpg);base64,/,"") let photo = dataURLtoFile(pic,createPic()) //转文件流 $('#photoName').text(photo.name) modalClose() console.log(photo) } //产生随机图片名称 function createPic(){ var now = new Date() var year = now.getFullYear() //得到年份 var month = now.getMonth()//得到月份 var date = now.getDate()//得到日期 var hour = now.getHours()//得到小时 var minu = now.getMinutes()//得到分钟 month = month + 1 if (month < 10) month = '0' + month if (date < 10) date = '0' + date var number = now.getSeconds()%43 //这将产生一个基于目前时间的0到42的整数。 var time = year + month + date + hour + minu var enNum = [] for(var i=0;i<4;i++){ var ranNum = Math.ceil(Math.random() * 25) //生成一个0到25的数字 //大写字母'A'的ASCII是65,A~Z的ASCII码就是65 + 0~25然后调用String.fromCharCode()传入ASCII值返回相应的字符并push进数组里 enNum.push(String.fromCharCode(65 + ranNum)) } return time+'_'+number+enNum.join('')+'.png' } //base64转文件流 function dataURLtoFile(dataurl, filename) { // 将base64编码转为字符串 const bstr = window.atob(dataurl) let n = bstr.length const u8arr = new Uint8Array(n) // 创建初始化为0的,包含length个元素的无符号整型数组 while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], filename, { type: 'image/png' }) } //关闭弹框 function modalClose(){ $('#cameraModal').modal('hide') if(cameraIsOpen){ mediaStreamTrack.stop() // 关闭摄像头 } }
复制