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>