需求: 某知名化妆品牌,要做个在线问卷调查。需要试用着自拍上传

注:使用navigator.mediaDevices.getUserMedia 需要使用https请求协议否者视为不安全,无法访问,开发阶段需要将启动改为https 在package.json中

前端开发环境启动项目将http协议改为https协议

授权,默认前置,切换后置

注意切换摄像头时要注意,一定要像关闭摄像头不然会有问题在部分手机上

import {Button,Dialog,ImageUploader,Modal,Popup,Toast,} from 'antd-mobile';import React, { useEffect, useState } from 'react';import { useRef } from 'react';import { history } from 'umi';import {uploadFile,getProjectInfo,saveUploadFile,deleteFile,getQuestionsByResultId,} from '@/app/request/requestApi'; // 接口import { ImageUploadItem } from 'antd-mobile/es/components/image-uploader';import { CameraOutline, ExclamationCircleFill } from 'antd-mobile-icons';import './style.less';const index = (props: any) => {const [fileList, setFileList] = useState([]);const [projectInfo, setProjectInfo] = useState({});const [visible, setVisible] = useState(false);const [rotvisible, setRotVisible] = useState(false);const [direction, setDirection] = useState(0);const [language, setLanguage] = useState('ZH');useEffect(() => {setLanguage(localStorage.getItem('language') " /> {if (navigator.mediaDevices.getUserMedia) {//最新的标准APInavigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);} else if (navigator.webkitGetUserMedia) {//webkit核心浏览器navigator.webkitGetUserMedia(constraints, success, error);} else if (navigator.mozGetUserMedia) {//firfox浏览器navigator.mozGetUserMedia(constraints, success, error);} else if (navigator.getUserMedia) {//旧版APInavigator.getUserMedia(constraints, success, error);}};const success = (stream: any) => {//兼容webkit核心浏览器let CompatibleURL = window.URL || window.webkitURL;//将视频流设置为video元素的源let videoElement = document.getElementById('video');//@ts-ignorevideoElement.srcObject = stream;//@ts-ignorevideoElement.play();};const error = (error: any) => {alert(`访问用户媒体设备失败${error.name}, ${error.message}`);console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);};return ({projectInfo.projectName}<ImageUploaderstyle={{ '--cell-size': '98px' }}value={fileList}onDelete={(item: any) => {console.log(item);return Dialog.confirm({content: '是否确认删除',}).then((res) => {if (!res) {return false;} else {return deleteFile({id: item.id,}).then((res) => {if (res.success) {return true;} else {Dialog.alert({content: res.msg,onConfirm: () => {//history.push('../');},});return false;}});}});}}onChange={(files) => {setFileList(files);}}disableUpload={true}upload={onUpload}children={{width: 98,height: 98,//borderRadius: 40,backgroundColor: '#f5f5f5',display: 'flex',justifyContent: 'center',alignItems: 'center',color: '#999999',}}> {Dialog.alert({content:language == 'ZH'? '请摘掉眼镜,露出额头和耳朵,在光线明亮的地方,原地旋转每30度左右拍一张,共6张': 'Please take off your glasses, expose your forehead and ears, and take a picture every 60 degrees or so in a bright place. A total of 6 pictures',onConfirm: () => {setVisible(true);},});}}style={{ fontSize: 32 }}/>}/>{ marginLeft: '20px' }}><ExclamationCircleFill style={{ color: 'rgb(255,51,102)' }} />{language == 'ZH'? '上传图片需最少六张图片才可进入下一步': 'A minimum of six images are required to upload images to proceed to the next step'}{position: 'absolute',bottom: '8px',textAlign: 'center',width: '100%',}}> {if (fileList.length  {if (res.success) {if (!projectInfo.timeId) {Modal.show({closeOnMaskClick: false,bodyStyle: {width: '270px',height: '220px',textAlign: 'center',paddingTop: '47px',},showCloseButton: false,header: null,actions: [],content: ({marginTop: '14px',fontSize: '14px',fontWeight: 'bold',color: '#333333',}}>{' '}{language == 'ZH'? '感谢您的参与!': 'Thank you for your participation.'}),});return;}localStorage.setItem('resultId', res.data);localStorage.setItem('files', JSON.stringify(fileList));getQuestionsByResultId({resultId: res.data,}).then((res) => {if (res.success) {localStorage.setItem('question',JSON.stringify(res.data.projectTimeInfo[0]),);history.push('form');} else {Dialog.alert({content: res.msg,onConfirm: () => {},});}});} else {Dialog.alert({content: res.msg,onConfirm: () => {},});}});}}>{language == 'ZH' ? ' 下一步 >' : 'Next >'} {setVisible(false);}}forceRender={true}position="top"bodyStyle={{minWidth: '100%',minHeight: '100%',backgroundColor: 'black',}}>{width: '100%',height: '60px',textAlign: 'center',lineHeight: '75px',paddingLeft: '80%',}}>// 切换摄像头 {setDirection(direction == 1 ? 0 : 1);console.log('切换摄像头');}}style={{ fontSize: '30px', lineHeight: '60px', color: 'white' }}/>//video 视频 {setVisible(false);}}style={{position: 'absolute',left: '20px',bottom: '30px',backgroundColor: 'transparent',border: 'none',zIndex: '999',color: 'white',}}>取消 // 拍照截取当前帧绘制到画布上// 主要是获取摄像头的视频流并显示在Video 签中 {var canvas = document.getElementById('canvas');canvas.width = document.getElementById('video')?.offsetWidth;canvas.height = document.getElementById('video')?.offsetHeight;//@ts-ignorecanvas?.getContext('2d')?.drawImage(document.getElementById('video'),0,0,document.getElementById('video')?.offsetWidth,document.getElementById('video')?.offsetHeight,);canvas.getContext('2d')?.canvas.toBlob((blob: any) => {let files = new window.File([blob],new Date().getTime() + '.jpg',);let formData = new FormData();formData.append('projectId', projectInfo.projectId);formData.append('projectTimeId', projectInfo.timeId);formData.append('phone',model,// navigator.userAgent.split('AppleWebKit')[0],);formData.append('fileInfos', files);setVisible(false);uploadFile(formData).then((res) => {if (res.success) {setFileList([...fileList,{key: new Date().getTime(),url: URL.createObjectURL(files),id: res.data[0].id,},]);} else {Dialog.alert({content: res.msg,onConfirm: () => {},});}});},'image/jpeg',0.7,);//@ts-ignorevar cutAvater = canvas.getContext('2d')?.canvas.toDataURL(0.7);var arr = cutAvater?.split(',');//@ts-ignorevar data = window.atob(arr[1]);//@ts-ignorevar mime = arr[0].match(/:(.*?);/)[1];var ia = new Uint8Array(data.length);for (var i = 0; i <canvasstyle={{ position: 'absolute', left: '-1500px' }} // // >);};export default index;

main {padding: 24px 24px 16px;display: flex;}video {margin-right: 16px;box-sizing: content-box;//border: 4px solid #ffaabb;}canvas {box-sizing: content-box;border: 4px solid #aabbff;}.actions {padding: 0 24px;}.actions button {margin-right: 16px;}.imgSuccess {width: 142px;height: 119px;background: url('../../../assets/images/success.png') no-repeat;background-size: 100%;border: 1px dashed gray;}.projectTitle {display: block;font-size: 26px;color: #b18b35;font-weight: bold;font-family: 'MicrosoftYaHei-Bold';margin: 20px 0 21px 20px;}.adm-image-uploader .adm-space-item {width: 100px;height: 100px;border: 1px dashed black;padding-bottom: 0px !important;margin-top: 10px;}.adm-image-uploader {margin-bottom: 40px;}.adm-image-uploader {margin-left: 20px;}.adm-text-area-element {background-color: #ffffff !important;}.btnNext {color: white;font-size: 12px;font-weight: bold;background-color: #b18b34;border: none;width: 236px;height: 39px;border-radius: 18px;}.adm-image-img {// width: auto;// height: 100%;// margin:0 auto;}.camerBtn {font-size: 60px;color: white;}.divBtn {position: absolute;bottom: 0px;width: 100%;height: 80px;text-align: center;}