vue 手势解锁组件

2022-08-13  本文已影响0人  littlesunn
image.png
<!-- <template>
  <div class='scratchable-container' 
  @touchmove="onMousemove($event)"
   @ontouchend="onMouseup"
   >
    <div class="box" v-for="(item, index) in boxs" :key="index" :ref="'box'+index">
      <div :class="['ponint', {selected: item.selected}]" 
      @touchstart.once="onMouseDown($event, index)" 
      @touchenter.once="onMouseEnter($event, index)"
      ></div>
    </div>
    <svg class="svg-wrap">
      <polyline :points="pointsStr" style="fill:none;stroke:#a8071a;stroke-width:4;stroke-linejoin:round" />
    </svg>
  </div>
</template> -->
<template>
  <div class='scratchable-container' @mousemove="onMousemove($event)" @mouseup="onMouseup">
    <div class="box" v-for="(item, index) in boxs" :key="index" :ref="'box'+index">
      <div :class="['ponint', {selected: item.selected}]" @mousedown.once="onMouseDown($event, index)" @mouseenter.once="onMouseEnter($event, index)">
        <div class="dot" :style="{
            display: item.selected ? 'inline-block' : 'none'
        }"></div>
      </div>
    </div>
    <svg class="svg-wrap">
      <polyline :points="pointsStr" style="fill:none;stroke:#a8071a;stroke-width:4;stroke-linejoin:round" />
    </svg>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      selectIndex: -1,
      points: [],
      line: null,
      contianer: null,
      selected: false,
      boxs: [],
      sortNum: []
    }
  },
  created() {
    for (let index = 0; index < 9; index++) {
      this.boxs.push(
        {
          selected: false,
        }
      )
    }
  },
  mounted() {
    this.contianer = document.querySelector(".scratchable-container");
    this.line = document.querySelector(".scratchable-container>svg>polyline");
  },
  methods: {
    onMouseDown(e, index) {
      this.sortNum.push(index)
      this.selected = true;
      this.boxs[index].selected = true;
      this.points.push(`${e.target.parentNode.offsetLeft + 50}, ${e.target.parentNode.offsetTop + 50}`)
      this.points.push("")
    },
    onMousemove(e) {
      if (!this.selected) {
        return;
      }
      this.points[this.points.length - 1] = `${e.clientX - this.contianer.getBoundingClientRect().x}, ${e.clientY - this.contianer.getBoundingClientRect().y}`
      this.line.setAttribute("points", this.points.join(" "))
    },
    onMouseEnter(e, index) {
      if (!this.selected) {
        return;
      }
      this.sortNum.push(index)
      this.boxs[index].selected = true;
      this.selectIndex = index;
      if (this.points.length > 0) {
        this.points[this.points.length - 1] = `${e.target.parentNode.offsetLeft + 50}, ${e.target.parentNode.offsetTop + 50}`
      } else {
        this.points.push(`${e.target.parentNode.offsetLeft + 50}, ${e.target.parentNode.offsetTop + 50}`)
      }
      this.points.push("")
    },
    onMouseup() {
      this.selected = false;
      this.selectIndex = -1
      this.points.pop();
      console.log("密码是: " + this.sortNum.toString());
    },
  },
  computed: {
    pointsStr() {
      console.log(123123);
      return this.points.join(" ")
    }
  },
}
</script>

<style scoped lang='scss'>
.scratchable-container {
  display: flex;
  width: 300px;
  flex-wrap: wrap;
  position: relative;
  background: #f5f5f5;
  backdrop-filter: filter(10);
  border-radius: 10px;
}
.box {
  width: 100px;
  height: 100px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  &:focus {
    .ponint {
      box-shadow: 0 0 0px 0px #ffccc7;
    }
  }
  .ponint {
    width: 50%;
    height: 50%;
    border-radius: 50%;
    transition: 0.25s;
    box-shadow: 0 0 0px 4px #ccc;
    position: relative;
    &.selected {
      background: #ff7875;
      box-shadow: 0 0 0px 10px #ffccc7;
    }
  }
  .dot {
    width: 24%;
    height: 24%;
    border-radius: 50%;
    background: #820014;
    z-index: 10;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}
.svg-wrap {
  pointer-events: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
</style>
上一篇 下一篇

猜你喜欢

热点阅读