失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > html 图片滑动验证码 html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】...

html 图片滑动验证码 html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】...

时间:2021-04-03 17:23:16

相关推荐

html 图片滑动验证码 html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】...

电脑和手机移动端都适用的jQuery拖动滑块图片拼图验证码插件,通过鼠标拖动或触屏滑动填充拼图来进行安全验证,点击刷新可以更换当前待验证的图片。

HTML & css:

拖动滑块图片拼图验证码插件

.slidercaptcha {

margin: 0 auto;

width: 314px;

height: 286px;

border-radius: 4px;

box-shadow: 0 0 10px rgba(0, 0, 0, 0.125);

margin-top: 40px;

}

.slidercaptcha .card-body {

padding: 1rem;

}

.slidercaptcha canvas:first-child {

border-radius: 4px;

border: 1px solid #e6e8eb;

}

.slidercaptcha.card .card-header {

background-image: none;

background-color: rgba(0, 0, 0, 0.03);

}

.refreshIcon {

top: -54px;

}

请完成安全验证

$('#captcha').sliderCaptcha({

repeatIcon: 'fa fa-redo',

setSrc: function () {

return '/Pic' + Math.round(Math.random() * 136) + '.jpg';

},

onSuccess: function () {

alert('验证通过!');

}

});

disk/slidercaptcha.css:

body {

overflow-x: hidden;

}

.block {

position: absolute;

left: 0;

top: 0;

}

.sliderContainer {

position: relative;

text-align: center;

line-height: 40px;

background: #f7f9fa;

color: #45494c;

border-radius: 2px;

}

.sliderbg {

position: absolute;

left: 0;

right: 0;

top: 0;

background-color: #f7f9fa;

height: 40px;

border-radius: 2px;

border: 1px solid #e6e8eb;

}

.sliderContainer_active .slider {

top: -1px;

border: 1px solid #1991FA;

}

.sliderContainer_active .sliderMask {

border-width: 1px 0 1px 1px;

}

.sliderContainer_success .slider {

top: -1px;

border: 1px solid #52CCBA;

background-color: #52CCBA !important;

}

.sliderContainer_success .sliderMask {

border: 1px solid #52CCBA;

border-width: 1px 0 1px 1px;

background-color: #D2F4EF;

}

.sliderContainer_success .sliderIcon:before {

content: "\f00c";

}

.sliderContainer_fail .slider {

top: -1px;

border: 1px solid #f57a7a;

background-color: #f57a7a !important;

}

.sliderContainer_fail .sliderMask {

border: 1px solid #f57a7a;

background-color: #fce1e1;

border-width: 1px 0 1px 1px;

}

.sliderContainer_fail .sliderIcon:before {

content: "\f00d";

}

.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;

border-radius: 2px;

}

.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;

border-radius: 2px;

display: flex;

align-items: center;

justify-content: center;

}

.slider:hover {

background: #1991FA;

}

.slider:hover .sliderIcon {

background-position: 0 -13px;

}

.sliderText {

position: relative;

}

.sliderIcon {

}

.refreshIcon {

position: absolute;

right: 0;

top: 0;

cursor: pointer;

margin: 6px;

color: rgba(0,0,0,.25);

font-size: 1rem;

z-index: 5;

transition: color .3s linear;

}

.refreshIcon:hover {

color: #6c757d;

}

disk/longbow.slidercaptcha.js:

(function ($) {

'use strict';

var SliderCaptcha = function (element, options) {

this.$element = $(element);

this.options = $.extend({}, SliderCaptcha.DEFAULTS, options);

this.$element.css({ 'position': 'relative', 'width': this.options.width + 'px', 'margin': '0 auto' });

this.init();

};

SliderCaptcha.VERSION = '1.0';

SliderCaptcha.Author = 'argo@';

SliderCaptcha.DEFAULTS = {

width: 280, // canvas宽度

height: 155, // canvas高度

PI: Math.PI,

sliderL: 42, // 滑块边长

sliderR: 9, // 滑块半径

offset: 5, // 容错偏差

loadingText: '正在加载中...',

failedText: '再试一次',

barText: '向右滑动填充拼图',

repeatIcon: 'fa fa-repeat',

maxLoadCount: 3,

localImages: function () {

return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';

}

};

function Plugin(option) {

return this.each(function () {

var $this = $(this);

var data = $this.data('lgb.SliderCaptcha');

var options = typeof option === 'object' && option;

if (data && !/reset/.test(option)) return;

if (!data) $this.data('lgb.SliderCaptcha', data = new SliderCaptcha(this, options));

if (typeof option === 'string') data[option]();

});

}

$.fn.sliderCaptcha = Plugin;

$.fn.sliderCaptcha.Constructor = SliderCaptcha;

var _proto = SliderCaptcha.prototype;

_proto.init = function () {

this.initDOM();

this.initImg();

this.bindEvents();

};

_proto.initDOM = function () {

var createElement = function (tagName, className) {

var elment = document.createElement(tagName);

elment.className = className;

return elment;

};

var createCanvas = function (width, height) {

var canvas = document.createElement('canvas');

canvas.width = width;

canvas.height = height;

return canvas;

};

var canvas = createCanvas(this.options.width - 2, this.options.height) // 画布

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

var sliderContainer = createElement('div', 'sliderContainer');

var refreshIcon = createElement('i', 'refreshIcon ' + this.options.repeatIcon);

var sliderMask = createElement('div', 'sliderMask');

var sliderbg = createElement('div', 'sliderbg');

var slider = createElement('div', 'slider');

var sliderIcon = createElement('i', 'fa fa-arrow-right sliderIcon');

var text = createElement('span', 'sliderText');

block.className = 'block'

text.innerHTML = this.options.barText;

var el = this.$element;

el.append($(canvas));

el.append($(refreshIcon));

el.append($(block));

slider.appendChild(sliderIcon);

sliderMask.appendChild(slider);

sliderContainer.appendChild(sliderbg);

sliderContainer.appendChild(sliderMask);

sliderContainer.appendChild(text);

el.append($(sliderContainer));

Object.assign(this, {

canvas,

block,

sliderContainer: $(sliderContainer),

refreshIcon,

slider,

sliderMask,

sliderIcon,

text: $(text),

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

blockCtx: block.getContext('2d')

})

};

_proto.initImg = function () {

var that = this;

var isIE = window.navigator.userAgent.indexOf('Trident') > -1;

var L = this.options.sliderL + this.options.sliderR * 2 + 3; // 滑块实际边长

var drawImg = function (ctx, operation) {

var l = that.options.sliderL;

var r = that.options.sliderR;

var PI = that.options.PI;

var x = that.x;

var y = that.y;

ctx.beginPath()

ctx.moveTo(x, y)

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

ctx.lineTo(x + l, y)

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

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

ctx.lineTo(x, y + l)

ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)

ctx.lineTo(x, y)

ctx.lineWidth = 2

ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'

ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'

ctx.stroke()

ctx[operation]()

ctx.globalCompositeOperation = isIE ? 'xor' : 'overlay'

}

var getRandomNumberByRange = function (start, end) {

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

};

var img = new Image();

img.crossOrigin = "Anonymous";

var loadCount = 0;

img.onload = function () {

// 随机创建滑块的位置

that.x = getRandomNumberByRange(L + 10, that.options.width - (L + 10));

that.y = getRandomNumberByRange(10 + that.options.sliderR * 2, that.options.height - (L + 10));

drawImg(that.canvasCtx, 'fill');

drawImg(that.blockCtx, 'clip');

that.canvasCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);

that.blockCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);

var y = that.y - that.options.sliderR * 2 - 1;

var ImageData = that.blockCtx.getImageData(that.x - 3, y, L, L);

that.block.width = L;

that.blockCtx.putImageData(ImageData, 0, y);

that.text.text(that.text.attr('data-text'));

};

img.onerror = function () {

loadCount++;

if (window.location.protocol === 'file:') {

loadCount = that.options.maxLoadCount;

console.error("can't load pic resource file from File protocal. Please try http or https");

}

if (loadCount >= that.options.maxLoadCount) {

that.text.text('加载失败').addClass('text-danger');

return;

}

img.src = that.options.localImages();

};

img.setSrc = function () {

var src = '';

loadCount = 0;

that.text.removeClass('text-danger');

if ($.isFunction(that.options.setSrc)) src = that.options.setSrc();

if (!src || src === '') src = 'https://picsum.photos/' + that.options.width + '/' + that.options.height + '/?image=' + Math.round(Math.random() * 20);

if (isIE) { // IE浏览器无法通过img.crossOrigin跨域,使用ajax获取图片blob然后转为dataURL显示

var xhr = new XMLHttpRequest()

xhr.onloadend = function (e) {

var file = new FileReader(); // FileReader仅支持IE10+

file.readAsDataURL(e.target.response);

file.onloadend = function (e) {

img.src = e.target.result;

}

}

xhr.open('GET', src);

xhr.responseType = 'blob';

xhr.send();

} else img.src = src;

};

img.setSrc();

this.text.attr('data-text', this.options.barText);

this.text.text(this.options.loadingText);

this.img = img

};

_proto.clean = function () {

this.canvasCtx.clearRect(0, 0, this.options.width, this.options.height);

this.blockCtx.clearRect(0, 0, this.options.width, this.options.height);

this.block.width = this.options.width;

};

_proto.bindEvents = function () {

var that = this;

this.$element.on('selectstart', function () {

return false;

});

$(this.refreshIcon).on('click', function () {

that.text.text(that.options.barText);

that.reset();

if ($.isFunction(that.options.onRefresh)) that.options.onRefresh.call(that.$element);

});

var originX, originY, trail = [],

isMouseDown = false

var handleDragStart = function (e) {

if (that.text.hasClass('text-danger')) return;

originX = e.clientX || e.touches[0].clientX;

originY = e.clientY || e.touches[0].clientY;

isMouseDown = true;

};

var handleDragMove = function (e) {

if (!isMouseDown) return false;

var eventX = e.clientX || e.touches[0].clientX;

var eventY = e.clientY || e.touches[0].clientY;

var moveX = eventX - originX;

var moveY = eventY - originY;

if (moveX < 0 || moveX + 40 > that.options.width) return false;

that.slider.style.left = (moveX - 1) + 'px';

var blockLeft = (that.options.width - 40 - 20) / (that.options.width - 40) * moveX;

that.block.style.left = blockLeft + 'px';

that.sliderContainer.addClass('sliderContainer_active');

that.sliderMask.style.width = (moveX + 4) + 'px';

trail.push(moveY);

};

var handleDragEnd = function (e) {

if (!isMouseDown) return false

isMouseDown = false

var eventX = e.clientX || e.changedTouches[0].clientX

if (eventX == originX) return false

that.sliderContainer.removeClass('sliderContainer_active');

that.trail = trail

var {

spliced,

verified

} = that.verify()

if (spliced && verified) {

that.sliderContainer.addClass('sliderContainer_success');

if ($.isFunction(that.options.onSuccess)) that.options.onSuccess.call(that.$element);

} else {

that.sliderContainer.addClass('sliderContainer_fail');

if ($.isFunction(that.options.onFail)) that.options.onFail.call(that.$element);

setTimeout(() => {

that.text.text(that.options.failedText);

that.reset();

}, 1000);

}

};

this.slider.addEventListener('mousedown', handleDragStart);

this.slider.addEventListener('touchstart', handleDragStart);

document.addEventListener('mousemove', handleDragMove);

document.addEventListener('touchmove', handleDragMove);

document.addEventListener('mouseup', handleDragEnd);

document.addEventListener('touchend', handleDragEnd);

document.addEventListener('mousedown', function () { return false; });

document.addEventListener('touchstart', function () { return false; });

};

_proto.verify = function () {

var sum = function (x, y) { return x + y; };

var square = function (x) { return x * x; };

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

var average = arr.reduce(sum) / arr.length;

var deviations = arr.map(function (x) { return x - average; });

var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);

var left = parseInt(this.block.style.left);

return {

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

verified: stddev !== 0, // 简单验证下拖动轨迹,为零时表示Y轴上下没有波动,可能非人为操作

}

};

_proto.reset = function () {

this.sliderContainer.removeClass('sliderContainer_fail sliderContainer_success');

this.slider.style.left = 0

this.block.style.left = 0

this.sliderMask.style.width = 0

this.clean()

this.text.attr('data-text', this.text.text());

this.text.text(this.options.loadingText);

this.img.setSrc();

};

})(jQuery);

附录1:需要注意css和js的引用路径;

总结

以上所述是小编给大家介绍的html+jQuery实现拖动滑块图片拼图验证码插件希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

如果觉得《html 图片滑动验证码 html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】...》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。