<template>
  <div class="verify-points">
    <div class="verify-points-logo">
      <img src="../assets/verify/verify-logo.png" alt="">
    </div>
    <div class="verify-points-panel">
      <div class="verify-points-panel-header">
        <span>请在下图依次点击：</span>
        <span>{{ textVerify }}</span>
      </div>
      <div class="verify-points-panel-main" @click="addPoint($event)" ref="pointsPanelMain">
        <img class="points-panel-img" :src="imgUrl || imgBase64AddPrefix(imgBase64)" alt="" ref="pointsPanelImg">
        <span
          class="icon-verify-point point"
          v-for="(item, index) in points"
          :style="{left: item.offsetX + 'px', top: item.offsetY + 'px'}"
          :key="item.id"
          ref="points"
          @click.stop.prevent="removePoint(item, index)"
        ></span>
      </div>
      <div class="verify-points-panel-footer">
        <span class="verify-refresh" @click="onRefresh"></span>
        <button class="confirm-button verify-confirm" @click="onConfirm">确定</button>
      </div>
    </div>
  </div>
</template>
<script>
// 参考vue2-verify/components/Verify/VerifyPoints.vue
// https://github.com/mizuka-wu/vue2-verify/

// 每个点的属性
class Point {
  constructor (offsetX, offsetY, x, y) {
    // offsetX/offsetY圆点的位置坐标
    this.offsetX = offsetX
    this.offsetY = offsetY
    // x/y选择的实际坐标(精确坐标)需要发送到后端进行验证
    this.x = x
    this.y = y
    this.id = Date.now()
  }
}

export default {
  name: 'VerifyPoints',
  props: {
    /**
     * 验证码图片地址
     */
    imgUrl: {
      type: String,
      default: ''
    },
    /**
     * 验证码图片base64
     */
    imgBase64: {
      type: String,
      default: ''
    },
    /**
     * 验证文字
     */
    textVerify: {
      type: String,
      default: ''
    },
    /**
     * 最多有几个点
     */
    pointsMaxCount: {
      type: Number,
      default: 3
    }
  },
  data () {
    return {
      points: []
    }
  },
  computed: {
    pointsCoordinate () {
      return this.points.map(item => {
        return `${parseInt(item.x)},${parseInt(item.y)}`
      })
    }
  },
  watch: {
    textVerify () {
      this.points = []
    }
  },
  methods: {
    imgBase64AddPrefix (base64) {
      if (base64) {
        return `data:image/png;base64,${base64}`
      } else {
        return ''
      }
    },
    createPoint (offsetX, offsetY, x, y) {
      return new Point(offsetX, offsetY, x, y)
    },
    addPoint (e) {
      if (this.points.length >= this.pointsMaxCount) return
      const pointsPanelMain = this.$refs.pointsPanelMain
      const pointsPanelMainRect = pointsPanelMain.getBoundingClientRect()
      // 校正坐标（圆点的半径）圆的位置看起来正确
      // 使用相似计算，以图片宽度256px为例，其下坐标点的半径为9
      const correctNum = parseInt(9 * (pointsPanelMainRect.width / 256))

      // offsetX/offsetY圆点的位置坐标(需要偏移进行微调) === pointDom.offsetX/offsetY
      // offset = 鼠标相对视口坐标 - pointsMain相对视口坐标 - 校正坐标
      const offsetX = e.clientX - pointsPanelMainRect.left - correctNum
      const offsetY = e.clientY - pointsPanelMainRect.top - correctNum

      // x/y选择的实际坐标(精确坐标)需要发送到后端进行判断
      const x = offsetX + correctNum
      const y = offsetY + correctNum

      const point = this.createPoint(offsetX, offsetY, x, y)
      this.points.push(point)
    },
    removePoint (item, index) {
      this.points.splice(index, 1)
    },
    onReset () {
      this.points = []
    },
    onRefresh () {
      this.onReset()
      this.$emit('refresh')
    },
    onConfirm () {
      if (this.points.length <= 0) return
      const imgWidth = this.$refs.pointsPanelImg.getBoundingClientRect().width
      const payload = {
        pointsCoordinate: this.pointsCoordinate,
        imgWidth: parseInt(imgWidth)
      }
      this.$emit('confirm', payload)
    }
  }
}
</script>
<style lang="scss" scoped>
$white: #fff;
$black: #000;
.confirm-button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #2abed1;
  border-radius: 4Px;
  color: $white;
  &:before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    background-color: $black;
    border: inherit;
    border-color: $black;
    border-radius: inherit;
    -webkit-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
    opacity: 0;
  }
  &:active:before {
    opacity: 0.1;
  }
}
.verify-points {
  position: relative;
  width: 280Px;
  transform-origin: center center;
  transition: transform 0.2s ease;
  .verify-points-logo {
    width: 100%;
    height: 160Px;
    img {
      width: 100%;
      height: 100%;
    }
  }
  .verify-points-panel {
    margin-top: -1Px;
    padding: 12Px;
    background-color: $white;
    border-radius: 4px;
    &-header {
      font-size: 16Px;
    }
    &-main {
      position: relative;
      margin: 10Px 0;
      min-height: 60Px;
    }
    &-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      height: 28Px;
    }
    .verify-refresh {
      width: 28Px;
      height: 28Px;
      background: transparent url(../assets/verify/verify-refresh.png) no-repeat;
      background-size: contain;
    }
    .verify-confirm {
      padding: 0 12Px;
      font-size: 16Px;
      height: 100%;
    }
  }
  .point {
    position: absolute;
    z-index: 5;
  }
  .icon-verify-point {
    display: inline-block;
    width: 18Px;
    height: 18Px;
    background: transparent url(../assets/verify/verify-check.png) no-repeat;
    background-size: contain;
  }
}

// 卡片适配不同屏幕的网页
// 屏幕大于 1024px 或小于 1440px 时应用该样式
@media screen and (min-width: 1024px) and (max-width: 1440px) {
  .verify-points {
    transform: scale(1.1);
  }
}
// 屏幕大于 1440px
@media screen and (min-width: 1440px) {
  .verify-points {
    transform: scale(1.2);
  }
}
</style>
