本文實例為大家分享了js canvas實現(xiàn)滑塊驗證的具體代碼,供大家參考,具體內(nèi)容如下
滑塊驗證
話不多說先上代碼想用的小伙伴可以直接使用,想了解的我后面會說下我的思路
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,//盒子的高度,當(dāng)設(shè)置圖片原比例顯示的時候這個參數(shù)就不好使了 id: new Date().getTime(), r: 9, //半圓的半徑 w: 40, //滑塊的寬度 imgOriginalScale: true, //圖片是否顯示原來比例 sliderLeft: 0,//滑塊的初始位置 rangeValue:4,//當(dāng)滑塊到什么范圍內(nèi)算正確 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) { //根據(jù)圖片的尺寸變化計算一下圖片原來的比例 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); //繪制滑塊部分 這里注意一定要先剪裁然后在繪制圖片(這里圖片要傳進(jìn)去不然沒有辦法控制) }; }, drawBlock(ctx, width, height, type, img) {//這里是二合一函數(shù),可以畫出陰影部分也切割出拼圖形狀的函數(shù) let { w, r, sliderLeft } = this; //這地方用隨機(jī)數(shù)每次顯示的位置都不同 var x = this.random(30, width - w - r - 1); //這里最大值為了不讓滑塊進(jìn)入隱藏所以要減去滑塊的寬度 有個半圓所以要減去半圓位置 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)"; //設(shè)置背景顏色 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) {//當(dāng)點擊小紅球的時候 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() {//鼠標(biāo)松開的時候清空狀態(tài) document.onmouseup = ()=> { document.onmousemove = null; if(this.sliderLeft<(this.x+this.rangeValue)&&this.sliderLeft>(this.x-this.rangeValue)){ console.log("恭喜你成功了") }else{//當(dāng)沒用選中的時候重置一下滑塊的位置 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 > |
這里我總結(jié)了下我遇到的難點
1.在開始的時候我不知道怎么畫這個拼圖的形狀,后來百度發(fā)現(xiàn)其實很簡單,就是用半圓和線拼接起來形成的圖形就是拼圖的形狀
2.怎么能把一個圖片只顯示拼圖那一塊呢,這也非常簡單就是用ctx.clip()這個函數(shù)就可以實現(xiàn),這里需要注意的是,你要先剪裁然后再加載圖片在canvas中不然他就無法剪裁。
關(guān)鍵代碼
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) { //這里是二合一函數(shù),可以畫出陰影部分也切割出拼圖形狀的函數(shù) let { w, r, sliderLeft } = this ; //w寬度,r圓的半徑sliderLeft是滑塊的初始位置 //這地方用隨機(jī)數(shù)每次顯示的位置都不同 var x = this .random(30, width - w - r - 1); //這里最大值為了不讓滑塊進(jìn)入隱藏所以要減去滑塊的寬度 有個半圓所以要減去半圓位置 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)" ; //設(shè)置背景顏色 ctx.stroke(); ctx[type](); if (img) { //這里為什么要在這里加載圖片呢,因為這個高度是動態(tài)的必須計算完之后在放進(jìn)去 //還有個原因是你要先剪裁在加載圖片 ctx.drawImage(img, - this .x, 0, width, height); } }, |
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/qq1248409755/article/details/114658859