php画拼图滑动验证,JS实现滑动拼图验证功能完整示例

本文实例讲述了JS实现滑动拼图验证功能。分享给大家供大家参考,具体如下:

先看一下效果图:

58c6866aa053627a254413b980bf9474.png

8ff1479c65d26b6589038082b9b0d765.png

2f2f407485f7f943e22a323fc47ccade.png

设置画布滑块属性

const l = 42, // 滑块边长

r = 10, // 滑块半径

w = 310, // canvas宽度

h = 155, // canvas高度

PI = Math.PI

const L = l + r * 2 // 滑块实际边长

设置背景图片:

图片链接地址可以自行更换

function getRandomImg() {

return 'https://picsum.photos/300/150/?image=' + getRandomNumberByRange(0, 100)

}

CSS部分代码:

.container {

width: 310px;

margin: 100px auto;

}

#msg {

width: 100%;

line-height: 40px;

font-size: 14px;

text-align: center;

}

a:link,

a:visited,

a:hover,

a:active {

margin-left: 100px;

color: #0366D6;

}

.block {

position: absolute;

left: 0;

top: 0;

}

.sliderContainer {

position: relative;

text-align: center;

width: 310px;

height: 40px;

line-height: 40px;

margin-top: 15px;

background: #f7f9fa;

color: #45494c;

border: 1px solid #e4e7eb;

}

.sliderContainer_active .slider {

height: 38px;

top: -1px;

border: 1px solid #1991FA;

}

.sliderContainer_active .sliderMask {

height: 38px;

border-width: 1px;

}

.sliderContainer_success .slider {

height: 38px;

top: -1px;

border: 1px solid #52CCBA;

background-color: #52CCBA !important;

}

.sliderContainer_success .sliderMask {

height: 38px;

border: 1px solid #52CCBA;

background-color: #D2F4EF;

}

.sliderContainer_success .sliderIcon {

background-position: 0 0 !important;

}

.sliderContainer_fail .slider {

height: 38px;

top: -1px;

border: 1px solid #f57a7a;

background-color: #f57a7a !important;

}

.sliderContainer_fail .sliderMask {

height: 38px;

border: 1px solid #f57a7a;

background-color: #fce1e1;

}

.sliderContainer_fail .sliderIcon {

background-position: 0 -83px !important;

}

.sliderContainer_active .sliderText,

.sliderContainer_success .sliderText,

.sliderContainer_fail .sliderText {

display: none;

}

.sliderMask {

position: absolute;

left: 0;

top: 0;

height: 40px;

border: 0 solid #1991FA;

background: #D1E9FE;

}

.slider {

position: absolute;

top: 0;

left: 0;

width: 40px;

height: 40px;

background: #fff;

box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);

cursor: pointer;

transition: background .2s linear;

}

.slider:hover {

background: #1991FA;

}

.slider:hover .sliderIcon {

background-position: 0 -13px;

}

.sliderIcon {

position: absolute;

top: 15px;

left: 13px;

width: 14px;

height: 10px;

background: url(img/tb.png) 0 -26px;

background-size: 34px 471px;

}

.refreshIcon {

position: absolute;

right: 0;

top: 0;

width: 34px;

height: 34px;

cursor: pointer;

background: url(img/tb.png) 0 -437px;

background-size: 34px 471px;

}

页面,页面只用放一个div就可以了

js部分代码,包括验证是否正确

(function(window) {

const l = 42, // 滑块边长

r = 10, // 滑块半径

w = 310, // canvas宽度

h = 155, // canvas高度

PI = Math.PI

const L = l + r * 2 // 滑块实际边长

function getRandomNumberByRange(start, end) {

return Math.round(Math.random() * (end - start) + start)

}

function createCanvas(width, height) {

const canvas = createElement('canvas')

canvas.width = width

canvas.height = height

return canvas

}

function createImg(onload) {

const img = createElement('img')

img.crossOrigin = "Anonymous"

img.onload = onload

img.onerror = () => {

img.src = getRandomImg()

}

img.src = getRandomImg()

return img

}

function createElement(tagName) {

return document.createElement(tagName)

}

function addClass(tag, className) {

tag.classList.add(className)

}

function removeClass(tag, className) {

tag.classList.remove(className)

}

function getRandomImg() {

return 'https://picsum.photos/300/150/?image=' + getRandomNumberByRange(0, 100)

}

function draw(ctx, operation, x, y) {

ctx.beginPath()

ctx.moveTo(x, y)

ctx.lineTo(x + l / 2, y)

ctx.arc(x + l / 2, y - r + 2, r, 0, 2 * PI)

ctx.lineTo(x + l / 2, y)

ctx.lineTo(x + l, y)

ctx.lineTo(x + l, y + l / 2)

ctx.arc(x + l + r - 2, y + l / 2, r, 0, 2 * PI)

ctx.lineTo(x + l, y + l / 2)

ctx.lineTo(x + l, y + l)

ctx.lineTo(x, y + l)

ctx.lineTo(x, y)

ctx.fillStyle = '#fff'

ctx[operation]()

ctx.beginPath()

ctx.arc(x, y + l / 2, r, 1.5 * PI, 0.5 * PI)

ctx.globalCompositeOperation = "xor"

ctx.fill()

}

function sum(x, y) {

return x + y

}

function square(x) {

return x * x

}

class jigsaw {

constructor(el, success, fail) {

this.el = el

this.success = success

this.fail = fail

}

init() {

this.initDOM()

this.initImg()

this.draw()

this.bindEvents()

}

initDOM() {

const canvas = createCanvas(w, h) // 画布

const block = canvas.cloneNode(true) // 滑块

const sliderContainer = createElement('div')

const refreshIcon = createElement('div')

const sliderMask = createElement('div')

const slider = createElement('div')

const sliderIcon = createElement('span')

const text = createElement('span')

block.className = 'block'

sliderContainer.className = 'sliderContainer'

refreshIcon.className = 'refreshIcon'

sliderMask.className = 'sliderMask'

slider.className = 'slider'

sliderIcon.className = 'sliderIcon'

text.innerHTML = '向右滑动滑块填充拼图'

text.className = 'sliderText'

const el = this.el

el.appendChild(canvas)

el.appendChild(refreshIcon)

el.appendChild(block)

slider.appendChild(sliderIcon)

sliderMask.appendChild(slider)

sliderContainer.appendChild(sliderMask)

sliderContainer.appendChild(text)

el.appendChild(sliderContainer)

Object.assign(this, {

canvas,

block,

sliderContainer,

refreshIcon,

slider,

sliderMask,

sliderIcon,

text,

canvasCtx: canvas.getContext('2d'),

blockCtx: block.getContext('2d')

})

}

initImg() {

const img = createImg(() => {

this.canvasCtx.drawImage(img, 0, 0, w, h)

this.blockCtx.drawImage(img, 0, 0, w, h)

const y = this.y - r * 2 + 2

const ImageData = this.blockCtx.getImageData(this.x, y, L, L)

this.block.width = L

this.blockCtx.putImageData(ImageData, 0, y)

})

this.img = img

}

draw() {

// 随机创建滑块的位置

this.x = getRandomNumberByRange(L + 10, w - (L + 10))

this.y = getRandomNumberByRange(10 + r * 2, h - (L + 10))

draw(this.canvasCtx, 'fill', this.x, this.y)

draw(this.blockCtx, 'clip', this.x, this.y)

}

clean() {

this.canvasCtx.clearRect(0, 0, w, h)

this.blockCtx.clearRect(0, 0, w, h)

this.block.width = w

}

bindEvents() {

this.el.onselectstart = () => false

this.refreshIcon.onclick = () => {

this.reset()

}

let originX, originY, trail = [],

isMouseDown = false

this.slider.addEventListener('mousedown', function(e) {

originX = e.x, originY = e.y

isMouseDown = true

})

document.addEventListener('mousemove', (e) => {

if(!isMouseDown) return false

const moveX = e.x - originX

const moveY = e.y - originY

if(moveX < 0 || moveX + 38 >= w) return false

this.slider.style.left = moveX + 'px'

var blockLeft = (w - 40 - 20) / (w - 40) * moveX

this.block.style.left = blockLeft + 'px'

addClass(this.sliderContainer, 'sliderContainer_active')

this.sliderMask.style.width = moveX + 'px'

trail.push(moveY)

})

document.addEventListener('mouseup', (e) => {

if(!isMouseDown) return false

isMouseDown = false

if(e.x == originX) return false

removeClass(this.sliderContainer, 'sliderContainer_active')

this.trail = trail

const {

spliced,

TuringTest

} = this.verify()

if(spliced) {

if(TuringTest) {

addClass(this.sliderContainer, 'sliderContainer_success')

this.success && this.success()

} else {

addClass(this.sliderContainer, 'sliderContainer_fail')

this.text.innerHTML = '再试一次'

this.reset()

}

} else {

alert("验证失败");

addClass(this.sliderContainer, 'sliderContainer_fail')

this.fail && this.fail();

//验证失败后,1秒后重新加载图片

setTimeout(() => {

this.reset()

}, 1000)

}

})

}

verify() {

const arr = this.trail // 拖动时y轴的移动距离

const average = arr.reduce(sum) / arr.length // 平均值

const deviations = arr.map(x => x - average) // 偏差数组

const stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length) // 标准差

const left = parseInt(this.block.style.left)

return {

spliced: Math.abs(left - this.x) < 10,

TuringTest: average !== stddev, // 只是简单的验证拖动轨迹,相等时一般为0,表示可能非人为操作

}

}

reset() {

this.sliderContainer.className = 'sliderContainer'

this.slider.style.left = 0

this.block.style.left = 0

this.sliderMask.style.width = 0

this.clean()

this.img.src = getRandomImg()

this.draw()

}

}

window.jigsaw = {

init: function(element, success, fail) {

new jigsaw(element, success, fail).init()

}

}

}(window))

jigsaw.init(document.getElementById('captcha'), function() {

alert("验证成功");

})

希望本文所述对大家JavaScript程序设计有所帮助。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值