Blame view

components/mpvueGestureLock/index.vue 3.39 KB
4b045f7c   刘淇   江阴初始化项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  <template>
  	<view class="gesture-lock" :class="{error:error}" :style="{width: containerWidth +'rpx', height:containerWidth +'rpx'}"
  	 @touchstart.stop="onTouchStart" @touchmove.stop="onTouchMove" @touchend.stop="onTouchEnd">
  		<!-- 同级 v-for 的 key 重复会有问题,需要套一层。 -->
  		<!-- 9 个圆 -->
  		<view>
  			<view v-for="(item,i) in circleArray" :key="i" class="cycle" :class="{check:item.check}" :style="{left:item.style.left,top:item.style.top,width:item.style.width,height:item.style.width}">
  			</view>
  		</view>
  		<view>
  			<!-- 已激活锁之间的线段 -->
  			<view v-for="(item,i) in lineArray" :key="i" class="line" :style="{left:item.activeLeft,top:item.activeTop,width:item.activeWidth,'-webkit-transform':'rotate('+item.activeRotate+')',transform:'rotate('+item.activeRotate+')'}">
  			</view>
  		</view>
  		<!-- 最后一个激活的锁与当前位置之间的线段 -->
  		<view class="line" :style="{left:activeLine.activeLeft,top:activeLine.activeTop,width:activeLine.activeWidth,'-webkit-transform':'rotate('+activeLine.activeRotate+')',transform:'rotate('+activeLine.activeRotate+')'}">
  		</view>
  	</view>
  </template>
  <script>
  	import GestureLock from './gestureLock';
  
  	export default {
  		name: 'index',
  		props: {
  			/**
  			 * 容器宽度
  			 */
  			containerWidth: {
  				type: [Number, String],
  				default: 0
  			},
  			/**
  			 * 圆的半径
  			 */
  			cycleRadius: {
  				type: [Number, String],
  				default: 0
  			},
  			/**
  			 * 已设定的密码
  			 */
  			password: {
  				type: Array,
  				default () {
  					return []
  				}
  			},
  		},
  		data() {
  			return {
  				gestureLock: {}, // 锁对象
  				circleArray: [], // 圆对象数组
  				lineArray: [], // 已激活锁之间的线段
  				activeLine: {}, // 最后一个激活的锁与当前位置之间的线段
  				error: false
  			}
  		},
  		methods: {
  			onTouchStart(e) {
  				this.gestureLock.onTouchStart(e);
  				this.refesh();
  			},
  
  			onTouchMove(e) {
  				this.gestureLock.onTouchMove(e);
  				this.refesh();
  			},
  
  			onTouchEnd(e) {
  				const checkPoints = this.gestureLock.onTouchEnd(e);
  				if (!this.password.length || checkPoints.join('') == this.password.join('')) {
  					this.refesh();
  					this.$emit('end', checkPoints);
  				} else {
  					this.error = true;
  					setTimeout(() => {
  						this.refesh();
  						this.$emit('end', checkPoints);
  					}, 800);
  				}
  
  			},
  			refesh() {
  				this.error = false;
  				this.circleArray = this.gestureLock.getCycleArray();
  				this.lineArray = this.gestureLock.getLineArray();
  				this.activeLine = this.gestureLock.getActiveLine();
  			}
  		},
  		mounted() {
  			this.gestureLock = new GestureLock(this.containerWidth, this.cycleRadius);
  			this.refesh();
  		}
  	}
  </script>
  
  <style scoped>
  	.gesture-lock {
  		margin: 0 auto;
  		position: relative;
  		box-sizing: border-box;
  		overflow: auto;
  	}
  
  	.gesture-lock .cycle {
  		box-sizing: border-box;
  		position: absolute;
  		border: 2px solid #66aaff;
  		border-radius: 50%;
  	}
  
  	.gesture-lock .cycle.check:after {
  		content: "";
  		display: block;
  		position: absolute;
  		width: 32%;
  		height: 32%;
  		border: 2px solid #66aaff;
  		border-radius: 50%;
  		top: 50%;
  		left: 50%;
  		transform: translate(-50%, -50%);
  	}
  
  	.gesture-lock .line {
  		height: 0;
  		border-top: 2px solid #66aaff;
  		position: absolute;
  		transform-origin: left center;
  	}
  
  	.gesture-lock.error .cycle.check,
  	.gesture-lock.error .cycle.check:after,
  	.gesture-lock.error .line {
  		border-color: #ffa197;
  	}
  </style>