本文實例為大家分享了js canvas實現滑塊驗證的具體代碼,供大家參考,具體內容如下
滑塊驗證
話不多說先上代碼想用的小伙伴可以直接使用,想了解的我后面會說下我的思路
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
< template > < div class = "sliderContent" > < div class = "imgDev" :style = "'width:' + width + 'px;'" > < canvas :id = "id" :width = "width" :height = "height" ></ canvas > < canvas class = "slider" :id = "id + 'sliderBlock'" :width = "width" :height = "height" :style = "'left:' + sliderLeft + 'px;'" ></ canvas > </ div > < div class = "moveSLider" :style = "'width:' + width + 'px'" > < div class = "react" @ mousedown.stop = "moveBall($event)" > < div class = "yuan" :style = "'left:' + (sliderLeft + 10) + 'px;'" ></ div > </ div > </ div > </ div > </ template > < script > export default { data() { return { width: 200,//盒子的寬度 height: 200,//盒子的高度,當設置圖片原比例顯示的時候這個參數就不好使了 id: new Date().getTime(), r: 9, //半圓的半徑 w: 40, //滑塊的寬度 imgOriginalScale: true, //圖片是否顯示原來比例 sliderLeft: 0,//滑塊的初始位置 rangeValue:4,//當滑塊到什么范圍內算正確 imgsrc:require("../assets/img/ver-2.png")//引入你想要的背景圖片 }; }, mounted() { this.init(); }, methods: { init() { this.loadImage(); }, loadImage() {//加載圖片 let mainDom = document.getElementById(this.id); let bg = mainDom.getContext("2d"); let blockDom = document.getElementById(this.id + "sliderBlock"); let block = blockDom.getContext("2d"); let imgsrc = this.imgsrc; let img = document.createElement("img"); img.style.objectFit = "scale-down"; img.src = imgsrc; img.onload = () => { if (this.imgOriginalScale) { //根據圖片的尺寸變化計算一下圖片原來的比例 mainDom.height = (img.height / img.width) * mainDom.width; blockDom.height = (img.height / img.width) * blockDom.width; } bg.drawImage(img, 0, 0, mainDom.width, mainDom.height); this.drawBlock(bg, mainDom.width, mainDom.height, "fill"); //繪制滑塊部分 this.drawBlock(block, blockDom.width, blockDom.height, "clip", img); //繪制滑塊部分 這里注意一定要先剪裁然后在繪制圖片(這里圖片要傳進去不然沒有辦法控制) }; }, drawBlock(ctx, width, height, type, img) {//這里是二合一函數,可以畫出陰影部分也切割出拼圖形狀的函數 let { w, r, sliderLeft } = this; //這地方用隨機數每次顯示的位置都不同 var x = this.random(30, width - w - r - 1); //這里最大值為了不讓滑塊進入隱藏所以要減去滑塊的寬度 有個半圓所以要減去半圓位置 var y = this.random(10, height - w - r - 1); if (type == "clip") {//這里要保證在兩個東西要在同一個y值上 x = sliderLeft; y = this.y; } else { this.x = x; this.y = y; } let PI = Math.PI; //繪制 ctx.beginPath(); //left ctx.moveTo(x, y); //top ctx.arc(x + (w + 5) / 2, y, r, -PI, 0, true); ctx.lineTo(x + w + 5, y); //right ctx.arc(x + w + 5, y + w / 2, r, 1.5 * PI, 0.5 * PI, false); ctx.lineTo(x + w + 5, y + w); //bottom ctx.arc(x + (w + 5) / 2, y + w, r, 0, PI, false); ctx.lineTo(x, y + w); ctx.arc(x, y + w / 2, r, 0.5 * PI, 1.5 * PI, true); ctx.lineTo(x, y); if (type == "clip") { ctx.shadowBlur = 10; ctx.shadowColor = "black"; } ctx.lineWidth = 1; ctx.fillStyle = "rgba(0, 0, 0, 0.4)"; //設置背景顏色 ctx.stroke(); ctx[type](); if (img) { ctx.drawImage(img, -this.x, 0, width, height); } ctx.globalCompositeOperation = "xor"; }, random(min, max) { return parseInt(Math.floor(Math.random() * (max - min)) + min); }, moveBall(e) {//當點擊小紅球的時候 var oldx = e.pageX; document.onmousemove = (e) => {//這里要綁定document對象不然你離開的他就不動了 var x = e.pageX; if(this.sliderLeft+x-oldx<=0){//這里判斷左邊界 this.sliderLeft = 0; }else if(this.sliderLeft+x-oldx>=this.width-this.r*2-this.w){//這里判斷右邊界 this.sliderLeft = this.width-this.r*2-this.w; }else{ this.sliderLeft += x - oldx; } oldx = x; }; this.laveBall(); }, laveBall() {//鼠標松開的時候清空狀態 document.onmouseup = ()=> { document.onmousemove = null; if(this.sliderLeft<(this.x+this.rangeValue)&&this.sliderLeft>(this.x-this.rangeValue)){ console.log("恭喜你成功了") }else{//當沒用選中的時候重置一下滑塊的位置 this.sliderLeft = 0; } }; }, }, }; </ script > < style lang = "scss" scoped> .moveSLider { position: relative; margin: 0 auto; height: 50px; .react { .yuan { position: absolute; left: 0; top: 50%; transform: translate(0, -50%); width: 30px; height: 30px; background-color: red; border-radius: 50%; cursor: pointer; } position: absolute; left: 0; top: 50%; transform: translate(0, -50%); width: 100%; height: 20px; background-color: rosybrown; } } .imgDev { position: relative; margin: 0 auto; .slider { position: absolute; left: 0; top: 0; background-color: transparent; } } </ style > |
這里我總結了下我遇到的難點
1.在開始的時候我不知道怎么畫這個拼圖的形狀,后來百度發現其實很簡單,就是用半圓和線拼接起來形成的圖形就是拼圖的形狀
2.怎么能把一個圖片只顯示拼圖那一塊呢,這也非常簡單就是用ctx.clip()這個函數就可以實現,這里需要注意的是,你要先剪裁然后再加載圖片在canvas中不然他就無法剪裁。
關鍵代碼
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
|
drawBlock(ctx, width, height, type, img) { //這里是二合一函數,可以畫出陰影部分也切割出拼圖形狀的函數 let { w, r, sliderLeft } = this ; //w寬度,r圓的半徑sliderLeft是滑塊的初始位置 //這地方用隨機數每次顯示的位置都不同 var x = this .random(30, width - w - r - 1); //這里最大值為了不讓滑塊進入隱藏所以要減去滑塊的寬度 有個半圓所以要減去半圓位置 var y = this .random(10, height - w - r - 1); if (type == "clip" ) { //這里要保證在兩個東西要在同一個y值上 x = sliderLeft; y = this .y; } else { this .x = x; this .y = y; } let PI = Math.PI; //繪制 ctx.beginPath(); //left ctx.moveTo(x, y); //top ctx.arc(x + (w + 5) / 2, y, r, -PI, 0, true ); ctx.lineTo(x + w + 5, y); //right ctx.arc(x + w + 5, y + w / 2, r, 1.5 * PI, 0.5 * PI, false ); ctx.lineTo(x + w + 5, y + w); //bottom ctx.arc(x + (w + 5) / 2, y + w, r, 0, PI, false ); ctx.lineTo(x, y + w); ctx.arc(x, y + w / 2, r, 0.5 * PI, 1.5 * PI, true ); ctx.lineTo(x, y); if (type == "clip" ) { ctx.shadowBlur = 10; ctx.shadowColor = "black" ; } ctx.lineWidth = 1; ctx.fillStyle = "rgba(0, 0, 0, 0.4)" ; //設置背景顏色 ctx.stroke(); ctx[type](); if (img) { //這里為什么要在這里加載圖片呢,因為這個高度是動態的必須計算完之后在放進去 //還有個原因是你要先剪裁在加載圖片 ctx.drawImage(img, - this .x, 0, width, height); } }, |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/qq1248409755/article/details/114658859