1
1
<template >
2
2
<!-- 本体部分 -->
3
- <div :id =" id"
4
- :class =" ['vue-puzzle-vcode', { show_: show }]"
3
+ <div :class =" ['vue-puzzle-vcode', { show_: show }]"
5
4
@mousedown =" onCloseMouseDown"
6
5
@mouseup =" onCloseMouseUp"
7
6
@touchstart =" onCloseMouseDown"
82
81
<script >
83
82
import resetSvg from " ./assets/reset.png" ;
84
83
export default {
85
- /** 私有数据 **/
86
- data () {
87
- return {
88
- mouseDown: false , // 鼠标是否在按钮上按下
89
- startWidth: 50 , // 鼠标点下去时父级的width
90
- startX: 0 , // 鼠标按下时的X
91
- newX: 0 , // 鼠标当前的偏移X
92
- pinX: 0 , // 拼图的起始X
93
- pinY: 0 , // 拼图的起始Y
94
- loading: true , // 是否正在加在中,主要是等图片onload
95
- isCanSlide: false , // 是否可以拉动滑动条
96
- error: false , // 图片加在失败会出现这个,提示用户手动刷新
97
- infoBoxShow: false , // 提示信息是否出现
98
- infoText: " " , // 提示等信息
99
- infoBoxFail: false , // 是否验证失败
100
- timer1: null , // setTimout1
101
- closeDown: false , // 为了解决Mac上的click BUG
102
- isSuccess: false , // 验证成功
103
- resetSvg,
104
- imgIndex: - 1 // 用于自定义图片时不会随机到重复的图片
105
- };
106
- },
107
- /** 父级参数 **/
108
84
props: {
109
- id: { type: String },
110
85
canvasWidth: { type: Number , default: 310 }, // 主canvas的宽
111
86
canvasHeight: { type: Number , default: 160 }, // 主canvas的高
112
87
// 是否出现,由父级控制
@@ -132,6 +107,29 @@ export default {
132
107
}
133
108
},
134
109
110
+ data () {
111
+ return {
112
+ mouseDown: false , // 鼠标是否在按钮上按下
113
+ startWidth: 50 , // 鼠标点下去时父级的width
114
+ startX: 0 , // 鼠标按下时的X
115
+ newX: 0 , // 鼠标当前的偏移X
116
+ pinX: 0 , // 拼图的起始X
117
+ pinY: 0 , // 拼图的起始Y
118
+ loading: false , // 是否正在加在中,主要是等图片onload
119
+ isCanSlide: false , // 是否可以拉动滑动条
120
+ error: false , // 图片加在失败会出现这个,提示用户手动刷新
121
+ infoBoxShow: false , // 提示信息是否出现
122
+ infoText: " " , // 提示等信息
123
+ infoBoxFail: false , // 是否验证失败
124
+ timer1: null , // setTimout1
125
+ closeDown: false , // 为了解决Mac上的click BUG
126
+ isSuccess: false , // 验证成功
127
+ imgIndex: - 1 , // 用于自定义图片时不会随机到重复的图片
128
+ isSubmting: false , // 是否正在判定,主要用于判定中不能点击重置按钮
129
+ resetSvg,
130
+ };
131
+ },
132
+
135
133
/** 生命周期 **/
136
134
mounted () {
137
135
document .body .appendChild (this .$el );
@@ -144,8 +142,9 @@ export default {
144
142
document .addEventListener (" touchend" , this .onRangeMouseUp , false );
145
143
if (this .show ) {
146
144
document .body .classList .add (" vue-puzzle-overflow" );
145
+ this .reset ();
147
146
}
148
- this . reset ();
147
+
149
148
},
150
149
beforeDestroy () {
151
150
clearTimeout (this .timer1 );
@@ -167,6 +166,8 @@ export default {
167
166
document .body .classList .add (" vue-puzzle-overflow" );
168
167
this .reset ();
169
168
} else {
169
+ this .isSuccess = false ;
170
+ this .infoBoxShow = false ;
170
171
document .body .classList .remove (" vue-puzzle-overflow" );
171
172
}
172
173
}
@@ -247,6 +248,10 @@ export default {
247
248
* @param withCanvas 是否强制使用canvas随机作图
248
249
*/
249
250
init (withCanvas ) {
251
+ // 防止重复加载导致的渲染错误
252
+ if (this .loading && ! withCanvas){
253
+ return ;
254
+ }
250
255
this .loading = true ;
251
256
this .isCanSlide = false ;
252
257
const c = this .$refs .canvas1 ;
@@ -255,7 +260,10 @@ export default {
255
260
const ctx = c .getContext (" 2d" );
256
261
const ctx2 = c2 .getContext (" 2d" );
257
262
const ctx3 = c3 .getContext (" 2d" );
263
+ const isFirefox = navigator .userAgent .indexOf (" Firefox" ) >= 0 && navigator .userAgent .indexOf (" Windows" ) >= 0 ; // 是windows版火狐
258
264
const img = document .createElement (" img" );
265
+ ctx .fillStyle = " rgba(255,255,255,1)" ;
266
+ ctx3 .fillStyle = " rgba(255,255,255,1)" ;
259
267
ctx .clearRect (0 , 0 , this .canvasWidth , this .canvasHeight );
260
268
ctx2 .clearRect (0 , 0 , this .canvasWidth , this .canvasHeight );
261
269
@@ -269,31 +277,26 @@ export default {
269
277
// 先画小图
270
278
this .paintBrick (ctx);
271
279
ctx .closePath ();
272
- if (
273
- ! (
274
- navigator .userAgent .indexOf (" Firefox" ) >= 0 &&
275
- navigator .userAgent .indexOf (" Windows" ) >= 0
276
- )
277
- ) {
278
- // 非火狐,在此画外阴影
280
+ if (! isFirefox){
281
+ ctx .shadowOffsetX = 0 ;
282
+ ctx .shadowOffsetY = 0 ;
283
+ ctx .shadowColor = " #000" ;
284
+ ctx .shadowBlur = 3 ;
285
+ ctx .fill ();
286
+ ctx .clip ();
287
+ } else {
288
+ ctx .clip ();
289
+ ctx .save ();
279
290
ctx .shadowOffsetX = 0 ;
280
291
ctx .shadowOffsetY = 0 ;
281
292
ctx .shadowColor = " #000" ;
282
293
ctx .shadowBlur = 3 ;
283
294
ctx .fill ();
295
+ ctx .restore ();
284
296
}
285
297
286
- ctx .clip (); // 按照外阴影区域切割
287
-
288
- ctx .save ();
289
- // 小图外阴影
290
- ctx .shadowOffsetX = 0 ;
291
- ctx .shadowOffsetY = 0 ;
292
- ctx .shadowColor = " #000" ;
293
- ctx .shadowBlur = 2 ;
294
- ctx .fill ();
295
- ctx .restore ();
296
298
ctx .drawImage (img, x, y, w, h);
299
+ ctx3 .fillRect (0 ,0 ,this .canvasWidth ,this .canvasHeight );
297
300
ctx3 .drawImage (img, x, y, w, h);
298
301
299
302
// 设置小图的内阴影
@@ -318,13 +321,8 @@ export default {
318
321
ctx .fill ();
319
322
320
323
// 将小图赋值给ctx2
321
- const imgData = ctx .getImageData (
322
- this .pinX - 3 , // 为了阴影 是从-3px开始截取,判定的时候要+3px
323
- this .pinY - 20 ,
324
- this .pinX + this .puzzleBaseSize + 5 ,
325
- this .pinY + this .puzzleBaseSize + 5
326
- );
327
- ctx2 .putImageData (imgData, 0 , this .pinY - 20 );
324
+ ctx2 .drawImage (c, this .pinX - 3 ,this .pinY - 20 ,this .pinX + this .puzzleBaseSize + 5 ,this .pinY + this .puzzleBaseSize + 5 ,
325
+ 0 , this .pinY - 20 , this .pinX + this .puzzleBaseSize + 5 , this .pinY + this .puzzleBaseSize + 5 );
328
326
329
327
// 清理
330
328
ctx .restore ();
@@ -521,6 +519,7 @@ export default {
521
519
},
522
520
// 开始判定
523
521
submit () {
522
+ this .isSubmting = true ;
524
523
// 偏差 x = puzzle的起始X - (用户真滑动的距离) + (puzzle的宽度 - 滑块的宽度) * (用户真滑动的距离/canvas总宽度)
525
524
// 最后+ 的是补上slider和滑块宽度不一致造成的缝隙
526
525
const x = Math .abs (
@@ -542,6 +541,7 @@ export default {
542
541
clearTimeout (this .timer1 );
543
542
this .timer1 = setTimeout (() => {
544
543
// 成功的回调
544
+ this .isSubmting = false ;
545
545
this .$emit (" success" , x);
546
546
}, 800 );
547
547
} else {
@@ -555,19 +555,28 @@ export default {
555
555
// 800ms后重置
556
556
clearTimeout (this .timer1 );
557
557
this .timer1 = setTimeout (() => {
558
+ this .isSubmting = false ;
558
559
this .reset ();
559
560
}, 800 );
560
561
}
561
562
},
562
- // 重置
563
- reset () {
563
+ // 重置 - 重新设置初始状态
564
+ resetState () {
564
565
this .infoBoxFail = false ;
565
566
this .infoBoxShow = false ;
566
- this .isCanSlide = true ;
567
+ this .isCanSlide = false ;
567
568
this .isSuccess = false ;
568
569
this .startWidth = this .sliderBaseSize ; // 鼠标点下去时父级的width
569
570
this .startX = 0 ; // 鼠标按下时的X
570
571
this .newX = 0 ; // 鼠标当前的偏移X
572
+ },
573
+
574
+ // 重置
575
+ reset () {
576
+ if (this .isSubmting ){
577
+ return ;
578
+ }
579
+ this .resetState ();
571
580
this .init ();
572
581
}
573
582
}
0 commit comments