<template>
  <div style="width: 100%; height: calc(100% - 67.5px); background: #fff">
    <div class="img">
      <div class="left">
        <div class="pFace">
          <img src="../assets/img/face.png" alt />
        </div>
        <div class="nav">{{ isdetected }}</div>
      </div>
      <div class="controlZ">
        <div id="screan" ref="dv">
          <img :src="img[0]" alt v-show="!isCamera" />
          <!--图片展示-->
          <video
            ref="video"
            id="video_cam"
            width="195"
            height="156"
            class="face"
            autoplay
            v-show="isCamera"
          ></video>
          <canvas ref="canvasDOM" width="195" height="156" class="kuang" v-show="isCamera"></canvas>
        </div>
        <div id="tou" ref="dv1">
          <img :src="img[2]" alt />
        </div>
        <div id="ai" ref="dv2">
          <img :src="img[1]" alt />
        </div>
        <div id="police" ref="dv2">
          <img :src="img[3]" alt />
        </div>
      </div>

      <div class="cameraZ">
        <!--开启摄像头-->
        <div class="cameraBtn">
          <!-- <el-button
            size="mini"
            type="primary"
            @click="callCamera"
            v-if="!isCamera"
          >开启摄像头</el-button-->
          <!-- > -->
          <div class="open" @click="callCamera" v-if="!isCamera">
            <img src="../assets/img/open.png" alt />
          </div>
          <!-- <el-button size="mini" type="primary" @click="closeCamera" v-else
            >关闭摄像头</el-button
          >-->
          <div class="close" @click="closeCamera" v-else>
            <img src="../assets/img/close.png" alt />
          </div>
          <!-- <el-button
            size="mini"
            type="primary"
            @click="photograph"
            v-if="isCamera"
            >确认保存</el-button
          >-->
          <div class="save" @click="photograph" v-if="isCamera">
            <img src="../assets/img/save.png" alt />
          </div>
          <div class="spot" @click="fnRun" v-if="isCamera">
            开始识别
          </div>
        </div>
        <!--确认-->
        <div v-if="isCamera" class="isPhoto">
          <!--canvas截取流-->
          <canvas ref="canvas" width="300" height="240" v-if="isCamera"></canvas>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import tracking from "@/assets/js/tracking-min.js";
import "@/assets/js/face-min.js";
import * as faceapi from "face-api.js";

export default {
  data() {
    return {
      that: this,
      img: [
        require("../assets/img/light/screan.png"),
        require("../assets/img/ai.png"),
        require("../assets/img/tou1.png"),
        require("../assets/img/policeNew.png")
      ],
      isCamera: false,
      count: 0,
      number: 0,
      isdetected: "请您保持脸部在画面中央",
      videoEl: {},
      canvasEL: {},
      // 预设样本图，支持本地，网络，beas64
      sampleArr: [
        {
          name: "编号1",
          img: []
        }
      ],
      // 匹配图，支持本地，网络，beas64
      detArr: [
        //"" 图片1
      ],
      // 匹配结果
      resultArr: [],
      // 人脸匹配矩阵数组对象转码结果
      faceMatcher: null
    };
  },
  methods: {
    // 调用摄像头
    callCamera() {
      let _this = this;
      // H5调用电脑摄像头API
      navigator.mediaDevices
        .getUserMedia({
          video: true
        })
        .then(success => {
          _this.isCamera = true;
          // 摄像头开启成功
          _this.$refs["video"].srcObject = success;
          // 实时拍照效果
          _this.$refs["video"].play();

          if (_this.$store.state.function.indexOf("face=1;") != -1) {
            // this.$message.error("摄像头开启失败，请检查摄像头是否可用！");

            const video = this.videoEl;
            const canvas = this.canvasEL;
            const canvasContext = canvas.getContext("2d");
            let tracker = new window.tracking.ObjectTracker("face");

            // video.pause();
            // video.src = "";
            tracker.setInitialScale(4);
            tracker.setStepSize(2);
            tracker.setEdgesDensity(0.1);
            window.tracking.track("#video_cam", tracker, { camera: true });
            tracker.on("track", function(event) {
              const { autoCaptureTrackTraking } = _this;
              canvasContext.clearRect(0, 0, canvas.width, canvas.height);
              event.data.forEach(function({ x, y, width, height }) {
                canvasContext.strokeStyle = "#FFFF";
                canvasContext.strokeRect(x + 10, y - 30, width - 20, height);
                canvasContext.font = "11px Helvetica";
                canvasContext.fillStyle = "#fff";
              });

              if (!(event.data.length == 0) && _this.count <= 10) {
                if (_this.count < 0) _this.count = 0;
                _this.count += 1;
                if (_this.count > 10) {
                  _this.isdetected = "已检测到人脸";
                }
              } else {
                _this.count -= 1;
                if (_this.count < 0)
                  _this.isdetected = "请您保持脸部在画面中央";
                //this.isdetected = '已检测到人脸，正在登录'
              }
            });
          }
        })
        .catch(error => {
          // console.error("摄像头开启失败，请检查摄像头是否可用！");
          _this.$message.error("摄像头开启失败，请检查摄像头是否可用！");
        });
    },
    // 拍照
    photograph() {
      let ctx = this.$refs["canvas"].getContext("2d");
      // 把当前视频帧内容渲染到canvas上
      ctx.drawImage(this.$refs["video"], 0, 0, 300, 240);
      // 转base64格式、图片格式转换、图片质量压缩
      let imgBase64 = this.$refs["canvas"].toDataURL("image/jpeg", 0.7); // 由字节转换为KB 判断大小

      let str = imgBase64.replace("data:image/jpeg;base64,", "");
      let strLength = str.length;
      let fileLength = parseInt(strLength - (strLength / 8) * 2); // 图片尺寸  用于判断
      let size = (fileLength / 1024).toFixed(2);
      console.log(size); // 上传拍照信息  调用接口上传图片 .........

      this.detArr.push(imgBase64);
      var json = {name:"",img:[]};
      json.name = "编号:" + this.number++;
      json.img.push(imgBase64);
      this.sampleArr.push(json);
      this.fnInit()
      // this.resultArr.push(imgBase64);

      // 保存到本地
      // this.isCamera = false;
      // let ADOM = document.createElement("a");
      // ADOM.href = imgBase64;
      // ADOM.download = new Date().getTime() + ".jpeg";
      // ADOM.click();
      // this.$message({
      //   message: "保存成功",
      //   type: "success"
      // });
    },
    // 关闭摄像头
    closeCamera() {
      if (!this.$refs["video"].srcObject) {
        this.isCamera = false;
        return;
      }
      let stream = this.$refs["video"].srcObject;
      let tracks = stream.getTracks();
      tracks.forEach(track => {
        track.stop();
      });
      this.$refs["video"].srcObject = null;
      this.isCamera = false;
    },

    // 初始化模型加载,匹配矩阵
    async fnInit() {
      // 加载模型
      await faceapi.loadFaceRecognitionModel("/static/models");
      // 生成人脸匹配矩阵数组对象，样本图片同步转码
      // const labeledFaceDescriptors = await Promise.all(
      //   this.sampleArr.map(async item => {
      //     // 临时图片转码数据，将图片对象转数据矩阵对象
      //     let descriptors = [];
      //     for (let image of item.img) {
      //       const imageEl = await faceapi.fetchImage(image);
      //       descriptors.push(await faceapi.computeFaceDescriptor(imageEl));
      //     }
      //     // 返回图片用户和图片转码数组
      //     return new faceapi.LabeledFaceDescriptors(item.name, descriptors);
      //   })
      // );
      // // 人脸匹配矩阵数组对象转码结果
      // this.faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors);
    },
    // 执行遍历识别匹配图片，数值误差越小越精确
    fnRun() {
      this.detArr.forEach(async img => {
        let ts = Date.now();
        // 将图片对象转数据矩阵对象，进行匹配
        const inputEl = await faceapi.fetchImage(img);
        const inputDescriptor = await faceapi.computeFaceDescriptor(inputEl);
        const bestMatch = await this.faceMatcher.findBestMatch(inputDescriptor);
        // 结果
        this.resultArr.push({
          target: img,
          result: bestMatch.toString(),
          time: Date.now() - ts + "ms",
          fps: Math.round(1000 / (Date.now() - ts))
        });
      });
    },
    // 更换匹配图
    async fnChange(e) {
      if (!e.target.files.length) return;
      this.detArr = [];
      this.resultArr = [];
      // 将文件显示为图像并识别
      e.target.files.forEach(async file => {
        let ts = Date.now();
        let img = await faceapi.bufferToImage(file);
        const inputDescriptor = await faceapi.computeFaceDescriptor(img);
        const bestMatch = await this.faceMatcher.findBestMatch(inputDescriptor);
        // 结果
        this.detArr.push(img.src);
        this.resultArr.push({
          target: file.name,
          result: bestMatch.toString(),
          time: Date.now() - ts + "ms",
          fps: Math.round(1000 / (Date.now() - ts))
        });
      });
    }
  },
  mounted() {
    // console.log(this.$store.state.function);
    // var _s3 = document.createElement("script");
    // _s3.src = "/static/materialize/jquery-2.1.3.min.js";
    // _s3.type = "text/javascript";
    // document.head.appendChild(_s3);
    // var _s2 = document.createElement("script");
    // _s2.src = "/static/camera.283d5d54.js";
    // _s2.type = "text/javascript";
    // document.head.appendChild(_s2);
    // var _s1 = document.createElement("script");
    // _s1.src = "/static/bundle.js";
    // _s1.type = "text/javascript";
    // document.head.appendChild(_s1);
    // console.log(this.$store.state.function);
    this.$nextTick(() => {
      // this.fnInit().then(() => this.fnRun());
    });

    if (this.$store.state.function.indexOf("screen=1;") != -1) {
      // this.$message.error("摄像头开启失败，请检查摄像头是否可用！");
      this.callCamera();
    }
    this.videoEl = this.$refs.video;
    this.canvasEL = this.$refs.canvasDOM;
  }
};
</script>

<style scoped>
html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
}

.tip {
  margin: 25px 0 30px 20px;
  width: 419px;
}

.tip > img,
#screan > img,
#tou > img,
#ai > img,
#police > img,
.right > img {
  width: 100%;
  height: 100%;
  user-select: none;
}

.img {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  justify-content: center;
  width: 100%;
  height: 100%;
  position: relative;
}

#screan {
  width: 185px;
  position: absolute;
  z-index: 5;
  top: 132px;
  left: 93px;
}

#ai {
  width: 185px;
  position: absolute;
  z-index: 3;
  top: 130px;
  left: 93px;
}

#tou {
  width: 65px;
  position: absolute;
  z-index: 4;
  top: 97px;
  left: 153px;
}

#police {
  width: 300px;
  position: absolute;
  z-index: 2;
  top: 30px;
  left: 35px;
}

.button {
  color: #fff;
  background: #8ca1de;
  width: 550px;
  height: 55px;
  font-size: 20px;
  text-align: center;
  line-height: 55px;
  position: absolute;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
  user-select: none;
}

.right {
  width: 40px;
  position: absolute;
  left: 55%;
  top: 70%;
  display: none;
}

.dark {
  background: #5b79d0;
  cursor: pointer;
}

.controlZ {
  width: 490px;
  height: 900px;
  /* margin-left: calc(50% - (490px / 2)); */
  position: relative;
}

.cameraZ {
  display: flex;
  height: 340px;
  flex-direction: column;
  flex-wrap: nowrap;
  width: 300px;
}

.cameraBtn {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cameraBtn button {
  margin: 0 0 10px 0;
}

.face {
  position: absolute;
  z-index: 1;
  padding: 5px 0px;
}

.kuang {
  padding: 26.5px 0;
  position: absolute;
  z-index: 2;
}

.pFace {
  width: 180px;
  margin: 0 auto;
  margin-top: 220px;
}

.close > img,
.save > img,
.pFace > img,
.open > img {
  width: 100%;
  height: 100%;
}

.cameraBtn {
  margin-top: 80px;
}

.close {
  margin-bottom: 25px;
}

.isPhoto {
  padding: 20px 0 0 0;
  box-sizing: border-box;
}

.nav {
  text-align: center;
  font-size: 32px;
  color: #ccc;
}

.spot{
  background: #64ff64;
    color: #fff;
    width: 140px;
    height: 40px;
    text-align: center;
    line-height: 40px;
    border-radius: 20px;
    margin-top: 25px;
    cursor: pointer;
}
</style>
