国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳

這篇具有很好參考價(jià)值的文章主要介紹了H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

需求: 某知名化妝品牌,要做個(gè)在線問(wèn)卷調(diào)查。需要試用著自拍上傳

注:使用navigator.mediaDevices.getUserMedia 需要使用https請(qǐng)求協(xié)議否者視為不安全,無(wú)法訪問(wèn),開(kāi)發(fā)階段需要將啟動(dòng)改為https 在package.json中

前端開(kāi)發(fā)環(huán)境啟動(dòng)項(xiàng)目將http協(xié)議改為https協(xié)議

H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳

?

?授權(quán),默認(rèn)前置,切換后置

注意切換攝像頭時(shí)要注意,一定要像關(guān)閉攝像頭不然會(huì)有問(wèn)題在部分手機(jī)上文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-504529.html

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<any[]>([]);
  const [projectInfo, setProjectInfo] = useState<any>({});
  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') ?? 'ZH');
  }, []);

  useEffect(() => {
    setTimeout(() => {
      document.getElementsByTagName('title')[0].text = '上傳圖片';
    }, 500);
    getProjectInfo().then((res) => {
      if (res.success) {
        localStorage.setItem('projectInfo', JSON.stringify(res.data));
        setProjectInfo(res.data);
      } else {
        Dialog.alert({
          content: res.msg,
          onConfirm: () => {
            history.push('../');
          },
        });
      }
    });
  }, []);
  useEffect(() => {
    if (!visible) {
       // 關(guān)閉
      if (document.getElementById('video')?.srcObject) {
        document.getElementById('video').srcObject.getTracks()[0].stop();
      }
      return;
    }
    if (
      //@ts-ignore
       // 開(kāi)啟
      navigator.mediaDevices.getUserMedia ||
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia ||
      navigator.oGetUserMedia
    ) {
      var facingMode: any = null;
      if (direction == 1) {
        facingMode = { exact: 'environment' };
      } else {
        facingMode = { exact: 'user' };
      }
      // 切換攝像頭需先關(guān)閉再打開(kāi)
      if (document.getElementById('video')?.srcObject) {
        document.getElementById('video').srcObject.getTracks()[0].stop();
      }
      //調(diào)用用戶媒體設(shè)備, 訪問(wèn)攝像頭
      getUserMedia(
        { video: { width: 480, height: 320, facingMode: facingMode } }, // user 前置
        success,
        error,
      );
    } else {
      alert('不支持訪問(wèn)用戶媒體');
    }
  }, [visible, direction]);
  let model: any = localStorage.getItem('model');
  const onUpload = async (file: any) => {
    let formData = new FormData();
    formData.append('projectId', projectInfo.projectId);
    formData.append('projectTimeId', projectInfo.timeId);
    formData.append('phone', model);
    formData.append('fileInfos', file);
    var res = await uploadFile(formData);
    if (res.success) {
      return {
        url: res.data[0].imageUrl,
      } as ImageUploadItem;
    } else {
      Dialog.alert({
        content: res.msg,
        onConfirm: () => {
          //history.push("../");
        },
      });
      return {
        url: URL.createObjectURL(file),
      } as ImageUploadItem;
    }
  };

  const getUserMedia = (constraints: any, success: any, error: any) => {
    if (navigator.mediaDevices.getUserMedia) {
      //最新的標(biāo)準(zhǔn)API
      navigator.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) {
      //舊版API
      navigator.getUserMedia(constraints, success, error);
    }
  };

  const success = (stream: any) => {
    //兼容webkit核心瀏覽器
    let CompatibleURL = window.URL || window.webkitURL;
    //將視頻流設(shè)置為video元素的源
    let videoElement = document.getElementById('video');
    //@ts-ignore
    videoElement.srcObject = stream;
    //@ts-ignore
    videoElement.play();
  };

  const error = (error: any) => {
    alert(`訪問(wèn)用戶媒體設(shè)備失敗${error.name}, ${error.message}`);
    console.log(`訪問(wèn)用戶媒體設(shè)備失敗${error.name}, ${error.message}`);
  };

  return (
    <>
      <span className="projectTitle">{projectInfo.projectName}</span>
      <ImageUploader
        style={{ '--cell-size': '98px' }}
        value={fileList}
        onDelete={(item: any) => {
          console.log(item);
          return Dialog.confirm({
            content: '是否確認(rèn)刪除',
          }).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={
          <div
            style={{
              width: 98,
              height: 98,
              //borderRadius: 40,
              backgroundColor: '#f5f5f5',
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              color: '#999999',
            }}
          >
            <CameraOutline
              onClick={() => {
                Dialog.alert({
                  content:
                    language == 'ZH'
                      ? '請(qǐng)摘掉眼鏡,露出額頭和耳朵,在光線明亮的地方,原地旋轉(zhuǎn)每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 }}
            />
          </div>
        }
      />
      <div style={{ marginLeft: '20px' }}>
        <ExclamationCircleFill style={{ color: 'rgb(255,51,102)' }} />
        <span>
          {language == 'ZH'
            ? '上傳圖片需最少六張圖片才可進(jìn)入下一步'
            : 'A minimum of six images are required to upload images to proceed to the next step'}
        </span>
      </div>
      <div
        style={{
          position: 'absolute',
          bottom: '8px',
          textAlign: 'center',
          width: '100%',
        }}
      >
        <Button
          className="btnNext"
          onClick={() => {
            if (fileList.length < 6) {
              Toast.show({
                icon: 'fail',
                content:
                  language == 'ZH'
                    ? '請(qǐng)至少上傳6張照片!'
                    : 'Please upload at least 6 photos!',
              });
              return;
            }

            saveUploadFile({
              projectId: projectInfo.projectId,
              projectTimeId: projectInfo.timeId,
              phone: model,
              PhoneUniqueId: localStorage.getItem('PhoneUniqueId'),
            }).then((res) => {
              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: (
                      <>
                        <img className="imgSuccess" />
                        <div
                          style={{
                            marginTop: '14px',
                            fontSize: '14px',
                            fontWeight: 'bold',
                            color: '#333333',
                          }}
                        >
                          {' '}
                          {language == 'ZH'
                            ? '感謝您的參與!'
                            : 'Thank you for your participation.'}
                        </div>
                      </>
                    ),
                  });
                  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 >'}
        </Button>
      </div>
      <Popup
        visible={visible}
        onMaskClick={() => {
          setVisible(false);
        }}
        forceRender={true}
        position="top"
        bodyStyle={{
          minWidth: '100%',
          minHeight: '100%',
          backgroundColor: 'black',
        }}
      >
        <div
          style={{
            width: '100%',
            height: '60px',
            textAlign: 'center',
            lineHeight: '75px',
            paddingLeft: '80%',
          }}
        >
          // 切換攝像頭
          <CameraOutline
            onClick={() => {
              setDirection(direction == 1 ? 0 : 1);
              console.log('切換攝像頭');
            }}
            style={{ fontSize: '30px', lineHeight: '60px', color: 'white' }}
          />
        </div>
        //  video 視頻
        <video
          id="video"
          width="100%"
          webkit-playsinline="true"
          playsInline={true}
        ></video>
        <Button
          onClick={() => {
            setVisible(false);
          }}
          style={{
            position: 'absolute',
            left: '20px',
            bottom: '30px',
            backgroundColor: 'transparent',
            border: 'none',
            zIndex: '999',
            color: 'white',
          }}
        >
          取消
        </Button>
         // 拍照截取當(dāng)前幀繪制到畫(huà)布上
        <div className="divBtn">
            // 主要是獲取攝像頭的視頻流并顯示在Video 簽中
          <CameraOutline
            onClick={() => {
              var canvas = document.getElementById('canvas');
              canvas.width = document.getElementById('video')?.offsetWidth;
              canvas.height = document.getElementById('video')?.offsetHeight;
              //@ts-ignore
              canvas
                ?.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-ignore
              var cutAvater = canvas.getContext('2d')?.canvas.toDataURL(0.7);
              var arr = cutAvater?.split(',');
              //@ts-ignore
              var data = window.atob(arr[1]);
              //@ts-ignore
              var mime = arr[0].match(/:(.*?);/)[1];
              var ia = new Uint8Array(data.length);
              for (var i = 0; i < data.length; i++) {
                ia[i] = data.charCodeAt(i);
              }
              var blob = new Blob([ia], { type: 'image/jpeg' });
            }}
            className="camerBtn"
          />
        </div>
      </Popup>
      <canvas
        style={{ position: 'absolute', left: '-1500px' }}
        id="canvas"
        // width="480"
        // height="320"
      ></canvas>
    </>
  );
};

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;
}

到了這里,關(guān)于H5 頁(yè)面通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭拍照上傳的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • H5頁(yè)面喚起手機(jī)撥打電話(撥號(hào))

    在移動(dòng)端頁(yè)面開(kāi)發(fā)中,偶爾會(huì)需要喚起用戶手機(jī)的打電話功能,撥打客服電話,此時(shí)我們可以按照以下操作實(shí)現(xiàn)打電話功能: 撥打電話 index.html在中加入這一段 js 或者 發(fā)送短信 index.html在 head/head 中加入這一段 js 或者 移動(dòng)web頁(yè)面自動(dòng)探測(cè)電話號(hào)碼 使用wtai協(xié)議進(jìn)行撥打電話

    2024年02月12日
    瀏覽(21)
  • 手機(jī)端H5頁(yè)面判斷是否橫屏

    之前,做了一個(gè)H5項(xiàng)目,需要在橫豎屏變化時(shí),做一些處理,一般先要判斷手機(jī)是否橫屏,在不同狀態(tài)下添加不同效果 方法一:JS判斷 移動(dòng)端的瀏覽器一般都支持window.orientation這個(gè)參數(shù),通過(guò)這個(gè)參數(shù)可以判斷出手機(jī)是處在橫屏還是豎屏狀態(tài) 屏幕方向?qū)?yīng)的window.orientation值:

    2024年02月11日
    瀏覽(20)
  • 微信小程序嵌套H5頁(yè)面,調(diào)用微信小程序掃碼功能,并將結(jié)果傳回H5頁(yè)面

    微信小程序嵌套H5頁(yè)面,調(diào)用微信小程序掃碼功能,并將結(jié)果傳回H5頁(yè)面

    實(shí)現(xiàn)方式: 小程序嵌套h5頁(yè)面,點(diǎn)擊h5頁(yè)面的掃碼按鈕跳轉(zhuǎn)到小程序的掃碼頁(yè)面,進(jìn)入之后會(huì)立即掃碼,拿到掃碼結(jié)果后,跳轉(zhuǎn)到小程序定義好的webview頁(yè)面,再由webview頁(yè)面進(jìn)入h5頁(yè)面。 缺點(diǎn):為了喚起掃碼,會(huì)進(jìn)入一個(gè)空白的掃碼頁(yè)面 1、小程序嵌套h5頁(yè)面方法 在小程序中,創(chuàng)

    2024年02月12日
    瀏覽(18)
  • uniapp H5頁(yè)面、小程序頁(yè)面獲取手機(jī)號(hào)撥打電話

    uniapp H5頁(yè)面、小程序頁(yè)面獲取手機(jī)號(hào)撥打電話

    效果圖: 1、H5頁(yè)面----手機(jī)號(hào)寫(xiě)死: 2、H5頁(yè)面----動(dòng)態(tài)獲取手機(jī)號(hào)撥打: APP: 小程序: methods:

    2024年02月07日
    瀏覽(30)
  • 記錄--h5調(diào)用手機(jī)攝像頭踩坑

    記錄--h5調(diào)用手機(jī)攝像頭踩坑

    一般業(yè)務(wù)也很少接觸攝像頭,有也是現(xiàn)成的工具庫(kù)掃個(gè)二維碼。難得用一次,記錄下踩坑。 這個(gè)就不用多說(shuō)了,缺點(diǎn)就是沒(méi)辦法自定義界面,它是調(diào)用的系統(tǒng)原生相機(jī)界面。 由于我需要自定義界面,就像下面這樣: 所以我選擇了這個(gè)方案,這個(gè) api 使用起來(lái)其實(shí)很簡(jiǎn)單: 可

    2024年02月08日
    瀏覽(27)
  • 微信小程序web-view嵌入uni-app H5頁(yè)面,通過(guò)H5頁(yè)面?zhèn)鲄⒔o小程序進(jìn)行轉(zhuǎn)發(fā)分享頁(yè)面,并通過(guò)點(diǎn)擊轉(zhuǎn)發(fā)出來(lái)的卡片,定向打開(kāi)對(duì)應(yīng)H5路徑

    index.wxml ?index.js 在H5項(xiàng)目的App.vue頁(yè)面獲取參數(shù)實(shí)現(xiàn)自動(dòng)跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面,包括攜帶的參數(shù)值

    2024年02月12日
    瀏覽(96)
  • ios手機(jī)在app中調(diào)試h5頁(yè)面

    ios手機(jī)在app中調(diào)試h5頁(yè)面

    網(wǎng)頁(yè)開(kāi)發(fā)在瀏覽器里調(diào)試很方便,但是在移動(dòng)端開(kāi)發(fā)調(diào)試,例如需要在app中打開(kāi),會(huì)用到一些bridge , 這時(shí)候就不能在瀏覽器調(diào)試。在app調(diào)試,如果每次都要發(fā)布到測(cè)試環(huán)境才能調(diào)試,那就會(huì)浪費(fèi)很多時(shí)間。 可以通過(guò)charls來(lái)做一個(gè)代理 從而在手機(jī)app里調(diào)試h5頁(yè)面 安裝charles 安裝

    2024年03月15日
    瀏覽(31)
  • h5調(diào)用手機(jī)攝像頭獲取圖片用于人臉識(shí)別

    1、安卓手機(jī)獲取前置攝像頭,并在video標(biāo)簽顯示 注:navigator.mediaDevices.getUserMedia文檔說(shuō)明兼容Safari11,實(shí)測(cè)不好用 2、蘋(píng)果手機(jī)獲取前置攝像頭拍照上傳,用于人臉識(shí)別 注:該方法在安卓手機(jī)也可使用 3、附件 //exif.js exif.js //rotate-photo.js rotate-photo.js

    2024年02月11日
    瀏覽(20)
  • 微信小程序中的H5頁(yè)面如何調(diào)用地理位置導(dǎo)航

    在微信小程序的H5頁(yè)面中,我們經(jīng)常需要使用地理位置導(dǎo)航功能,以便為用戶提供準(zhǔn)確的導(dǎo)航服務(wù)。下面將介紹如何在微信小程序的H5頁(yè)面中調(diào)用地理位置導(dǎo)航功能,并提供相應(yīng)的源代碼示例。 獲取用戶地理位置 在調(diào)用地理位置導(dǎo)航之前,首先需要獲取用戶的地理位置信息。

    2024年02月04日
    瀏覽(27)
  • 微信小程序通過(guò)掃一掃調(diào)用H5項(xiàng)目

    業(yè)務(wù)邏輯: 小程序?yàn)橹黧w,外鏈一個(gè)H5項(xiàng)目,相當(dāng)于在小程序webView幾個(gè)頁(yè)面及功能。 現(xiàn)需在小程序掃一掃點(diǎn)擊事件觸發(fā)后通過(guò)二維碼生成的url跳轉(zhuǎn)到H5項(xiàng)目相關(guān)頁(yè)面 PS:二維碼生成可查看這里 一、小程序 二、H5項(xiàng)目 PS:需求中遇到了這種情況,所以這里記錄一下,方便自己的

    2024年02月04日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包