| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- <template>
- <div id="">
- <el-dialog
- width="800px"
- class="take-photo"
- :visible.sync="takePhotoModal"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :show-close="false"
- >
- <div class="take-photo__content">
- <!-- <div class="take-photo__close" @click="takePhotoModal = false">X</div> -->
- <div class="take-photo__header">人脸验证</div>
- <div class="take-photo__body clearfix">
- <div class="left-box">
- <div class="title">重要提示:</div>
- <div class="content">
- <p>1、请保证摄像头正对自己,避免头像偏左或者偏右。</p>
- <p>
- 2、请保证拍照环境光线充足(照片太暗或曝光会降低验证通过率)。
- </p>
- <p>
- 3、请保证整个头像在人脸识别区域内,脸部无遮挡装饰物(佩戴眼镜会降低通过率)。
- </p>
- <p>
- 4、如果下面视频中出现黑屏,摄像头可能被其他进程占用,请关闭其他调用摄像头的程序,重新刷新当前页面重新拍照识别。
- </p>
- </div>
- </div>
- <div class="right-box">
- <img v-show="!isTaking" :src="faceUrl" alt="" />
- <video v-show="isTaking" id="video"></video>
- <div v-show="isTaking" class="mask"></div>
- </div>
- </div>
- <div class="take-photo__footer">
- <el-button
- type="primary"
- v-if="isTaking"
- class="take"
- :disabled="!successOpen"
- @click="onPhoto"
- >拍照</el-button
- >
- <el-button
- type="primary"
- v-if="!isTaking"
- class="take"
- :loading="loading"
- @click="reTake"
- >重拍</el-button
- >
- <el-button
- type="primary"
- v-if="!isTaking"
- :loading="loading"
- class="take"
- @click="takeOk"
- >确认</el-button
- >
- </div>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- export default {
- data() {
- return {
- successOpen:false,//是否授权拍照
- takePhotoModal: false,
- isTaking: true,
- loading: false,
- faceUrl: "",
- photoBadStatus:false,//摄像头无法使用触发true
- };
- },
- methods: {
- //拍照
- openPhoto() {
- var polyvPlayerContext = this.player;
- if (polyvPlayerContext) {
- this.isFullScreen();
- }
- this.successOpen = false
- this.faceUrl = "";
- this.loading = false;
- this.isTaking = true;
- this.takePhotoModal = true;
- this.$nextTick(() => {
- if (
- (window.navigator.mediaDevices &&
- window.navigator.mediaDevices.getUserMedia) ||
- window.navigator.getUserMedia ||
- window.navigator.webkitGetUserMedia ||
- window.navigator.mozGetUserMedia
- ) {
- // 调用用户媒体设备, 访问摄像头
- this.getUserMedia(
- {
- video: {
- width: 400,
- height: 400
- }
- },
- this.photographSuccess,
- this.photographError
- );
- } else {
- this.photographError();
- }
- });
- },
- //成功读取摄像头
- photographSuccess(stream) {
- // 兼容webkit核心浏览器
- // --虚拟摄像头
- if (this.isVirtualCamera(stream)) {
- return;
- }
- this.successOpen = true
- this.$nextTick(() => {
- const video = document.getElementById("video");
- // 将视频流设置为video元素的源
- video.srcObject = stream;
- video.play().catch(() => {});
- });
- },
- //未读取到摄像头 兼容webkit核心浏览器
- isVirtualCamera(stream) {
- const list = [
- "VCam",
- "ManyCam",
- "OBS",
- "ClassInCam",
- "Ev",
- "Video2Webcam"
- ];
- let isT = list.some(e => {
- return stream.getTracks()[0].label.indexOf(e) != -1;
- });
- if (isT) {
- this.photoBadStatus = true; //摄像头无法使用触发true
- this.$confirm("检测到你使用虚拟摄像头,无法继续学习。", "提示", {
- confirmButtonText: "返回",
- showConfirmButton: true,
- closeOnClickModal: false,
- showCancelButton: false,
- closeOnPressEscape: false,
- distinguishCancelAndClose: false,
- showClose: false
- }).then(() => {
- this.$router.go(-1);
- });
- }
- return isT;
- },
- //未读取到摄像头
- photographError(err) {
- this.photoBadStatus = true; //摄像头无法使用触发true
- this.$confirm(
- "课程学习需要开启摄像头进行拍照,经检测您的设备无摄像头可使用,请检测环境是否支持。",
- "提示",
- {
- confirmButtonText: "返回",
- showConfirmButton: true,
- closeOnClickModal: false,
- showCancelButton: false,
- closeOnPressEscape: false,
- distinguishCancelAndClose: false,
- showClose: false
- }
- ).then(() => {
- this.$router.back(-1);
- });
- },
- // 调用用户媒体设备, 访问摄像头
- getUserMedia(constraints, success, error) {
- if (window.navigator.mediaDevices.getUserMedia) {
- // 最新的标准API
- window.navigator.mediaDevices
- .getUserMedia(constraints)
- .then(success)
- .catch(error);
- } else if (window.navigator.webkitGetUserMedia) {
- // webkit核心浏览器
- window.navigator.webkitGetUserMedia(constraints, success, error);
- } else if (window.navigator.mozGetUserMedia) {
- // firfox浏览器
- window.navigator.mozGetUserMedia(constraints, success, error);
- } else if (window.navigator.getUserMedia) {
- // 旧版API
- window.navigator.getUserMedia(constraints, success, error);
- }
- },
- //判断是全屏则退出全屏
- isFullScreen() {
- if (!!(document.webkitIsFullScreen || this.fullele())) {
- try {
- var de = document;
- if (de.exitFullscreen) {
- de.exitFullscreen();
- } else if (de.mozCancelFullScreen) {
- de.mozCancelFullScreen();
- } else if (de.webkitCancelFullScreen) {
- de.webkitCancelFullScreen();
- }
- } catch (err) {}
- }
- },
- fullele() {
- return (
- document.fullscreenElement ||
- document.webkitFullscreenElement ||
- document.msFullscreenElement ||
- document.mozFullScreenElement ||
- null
- );
- },
- //拍照
- onPhoto() {
- const canvas = document.createElement("canvas");
- canvas.width = 400;
- canvas.height = 400;
- const context = canvas.getContext("2d");
- const video = document.getElementById("video");
- context.drawImage(video, 0, 0, 400, 400);
- this.faceUrl = canvas.toDataURL("image/png");
- this.isTaking = false;
- },
- //重拍-重置拍照
- reTake() {
- this.faceUrl = "";
- this.isTaking = true;
- this.getUserMedia({
- video: {
- width: 400,
- height: 400
- }
- });
- },
- //确认拍照
- async takeOk() {
- this.loading = true;
- this.$emit("returnParameter", this.faceUrl);
- this.takePhotoModal = false;
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .take-photo {
- /deep/ .el-dialog__header {
- display: none;
- }
- /deep/ .el-dialog__body {
- padding: 0;
- overflow: unset;
- }
- &__close {
- cursor: pointer;
- position: absolute;
- right: 0;
- top: -28px;
- width: 24px;
- height: 24px;
- line-height: 24px;
- text-align: center;
- color: #eee;
- border: 1px solid #eee;
- border-radius: 50%;
- }
- &__header {
- height: 40px;
- border-bottom: 1px solid #eee;
- line-height: 40px;
- font-size: 16px;
- font-family: Microsoft YaHei;
- font-weight: bold;
- color: #333333;
- padding-left: 24px;
- }
- &__body {
- // height: 400px;
- padding: 40px 24px;
- .left-box {
- width: 336px;
- float: left;
- .title {
- font-size: 16px;
- font-family: Microsoft YaHei;
- font-weight: bold;
- color: #ff3b30;
- line-height: 24px;
- }
- .content {
- font-size: 14px;
- font-family: Microsoft YaHei;
- font-weight: 400;
- color: #333333;
- line-height: 28px;
- margin-top: 32px;
- }
- }
- .right-box {
- float: right;
- width: 400px;
- height: 400px;
- position: relative;
- overflow: hidden;
- video {
- width: 100%;
- height: 100%;
- }
- .mask {
- width: 55%;
- height: 200px;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- margin: 30px auto 0;
- box-shadow: 0 0 0 2000px rgba(0, 0, 0, 0.4);
- }
- }
- }
- &__footer {
- height: 90px;
- border-top: 1px solid #eee;
- text-align: center;
- .take {
- display: inline-block;
- width: 200px;
- height: 40px;
- padding: 0;
- border-radius: 20px;
- text-align: center;
- line-height: 40px;
- margin: 24px auto;
- }
- }
- }
- </style>
|