js 滑動驗證
阿新 • • 發佈:2018-11-12
前言
看到B站的滑動驗證,便跟著做了一個。我檢查了b站的元素,發現它的背景圖片好像是切成了很多塊,可能是後臺處理的圖片放到前端。我這個案例是純html+css+js做的,可以在後臺取隨機數為滑動條驗證正確的x位置。但是這樣做可能安全性不高,以後再研究後臺處理圖片的方法。希望有大佬看到能夠提點。
效果
思路
1、放置一張背景圖片,在圖中指定範圍內生成一個拼圖凹槽(圖片)
2、在大圖下方放置滑動條,滑動時生成同x位置的拼圖圖片,並且y位置與拼圖凹槽一直,x值隨滑動條繫結。
3、當拼圖圖片x位置與拼圖凹槽一致,並且滑動條鬆開,則成功,否則失敗,並還原滑動條,銷燬兩個拼圖圖片。
關於如何獲取到被“摳”出的那塊圖片區域,我其實是將圖片複製,只顯示那個位置的區域,並用css的clip-path屬性裁剪出拼圖的形狀。這個方法很笨,主要我現在對css遮罩不瞭解。如果有更好的方法會馬上優化的,歡迎指正!~
程式碼
wxml
<view class='info' style='display:{{info?"block":"none"}}'> {{info_text}} </view> <view class='bar1' style="height:{{bar_height+200}}rpx;width:{{bar_width+20}}rpx;border-radius:{{bar_height/2}}rpx;background-image:url(../../images/bg.png);background-size:100% 100%;"> <!-- 活動的拼圖 --> <view class='pintu1 {{show?"show":"hide"}}' style='margin-left:{{left}}rpx;width:{{ball_width+20}}rpx;height:{{ball_width+20}}rpx;margin-top:{{top}}rpx;' bindtouchstart='touchS' bindtouchmove='touchM' bindtouchend='touchE'> <view style='width:{{ball_width+20}}rpx;height:{{ball_width+20}}rpx;background-image:url(../../images/bg.png);background-size:{{bar_width+20}}rpx {{bar_height+200}}rpx;position:absolute;z-index:2;background-repeat:no-repeat;background-position-x:{{-left_random}}rpx;background-position-y:{{-top}}rpx;clip-path: polygon(6% 22%, 31% 22%, 31% 6%, 53% 6%, 53% 22%, 77% 22%, 77% 47%, 93% 47%, 93% 68%, 77% 68%, 77% 93%, 53% 93%,53% 75%,31% 75%,31% 93%,6% 93%,6% 68%,24% 68%,24% 47%,6% 47%)'> </view> <view style='width:{{ball_width+20}}rpx;height:{{ball_width+20}}rpx;position:absolute;background:gray;clip-path: polygon(5% 21%, 30% 21%, 30% 5%, 54% 5%, 54% 21%, 78% 21%, 78% 46%, 93% 46%, 93% 69%, 78% 69%, 78% 94%, 52% 94%,52% 75%,31% 75%,31% 93%,6% 93%,6% 68%,24% 68%,24% 47%,6% 47%)'> </view> </view> <!-- 目標拼圖 --> <image src="../../images/pintu2_final.png" class='pintu2 {{show?"show":"hide"}}' style='margin-left:{{left_random}}rpx;width:{{ball_width+20}}rpx;height:{{ball_width+20}}rpx;margin-top:{{top}}rpx;'></image> </view> <!-- 控制條 --> <view class='bar' style="height:{{bar_height}}rpx;width:{{bar_width}}rpx;border-radius:{{bar_height}}rpx;"> <view class='ball' id="ball" style='margin-left:{{left}}rpx;width:{{ball_width}}rpx;' bindtouchstart='touchS' bindtouchmove='touchM' bindtouchend='touchE'></view> </view>
wxss
page{ background: #eee } .bar1{ background: #fff; margin: 50rpx auto; padding: 10rpx; display: flex; position: relative; z-index: 1; } .bar{ background: #fff; margin: 50rpx auto; padding: 10rpx; display: flex; align-items: center; position: relative; z-index: 1; } .road{ background: red; width:100%; height:100%; } .ball{ border-radius: 100%; background-color: #aaa; height: 100%; } .pintu1{ position: absolute; z-index: 3; } .pintu2{ position: absolute; z-index: 2; } .show{ display: block; } .hide{ display: none; } .info{ background: black; left: 50%; transform:translate(-50%, 0); opacity: 0.6; width: 300rpx; height: 200rpx; position: absolute; z-index: 3; top:85rpx; border-radius: 10rpx; color: white; line-height: 200rpx; text-align: center; }
js
Page({
data: {
left:0,
show:0
},
onLoad: function (options) {
},
onReady:function(e){
let self = this;
this.setData({
bar_width : 400,
bar_height : 50
})
//獲取小球高度
var query = wx.createSelectorQuery();
query.select('#ball').boundingClientRect()
query.exec(function (res) {
var h = res[0].height;
self.setData({
ball_width: h*2
})
})
const ctx = wx.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 75)
ctx.draw()
},
touchS:function(e){
this.data.start = e.touches[0].pageX;
this.data.start_left = this.data.left;
this.setData({
show:1,
top: Math.floor(Math.random() * (this.data.bar_height + 180 - this.data.ball_width)),
left_random: Math.floor(Math.random() * (this.data.bar_width-this.data.ball_width)/2+150)
})
},
touchM:function(e){
this.data.end = e.touches[0].pageX;
this.data.move = this.data.end - this.data.start;
this.data.end_left = this.data.start_left + this.data.move * 2;
if (this.data.end_left < 0){
this.setData({
left: 0
})
} else if (this.data.end_left > this.data.bar_width - this.data.ball_width){
this.setData({
left: this.data.bar_width - this.data.ball_width
})
}else{
this.setData({
left: this.data.end_left
})
}
},
touchE:function(e){
var info = '';
let that = this;
if (this.data.left > this.data.left_random - 10 && this.data.left < this.data.left_random + 10){
info='success'
}else{
info = 'fail'
}
this.setData({
info: 1,
info_text: info
})
setTimeout(function () {
that.setData({
info: 0,
show:0,
left:0
})
}, 1000)
}
})