热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

这篇文章主要介绍了html+jQuery实现拖动滑块图片拼图验证码插件,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

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

HTML & css:

















请完成安全验证
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@163.com'; 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 &#63; '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 + '/&#63;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)

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

总结

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


推荐阅读
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • Vue基础一、什么是Vue1.1概念Vue(读音vjuː,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • 视图分区_组复制常规操作网络分区amp;混合使用IPV6与IPV4 | 全方位认识 MySQL 8.0 Group Replication...
    网络分区对于常规事务而言,每当组内有事务数据需要被复制时,组内的成员需要达成共识(要么都提交,要么都回滚)。对于组成员资格的变更也和保持组 ... [详细]
  • 本文内容皆为作者原创,如需转载,请注明出处:https:www.cnblogs.comxuexianqip13045462.html1.自定义分页器的拷贝及使用当我们需要使用 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
  • 本文摘要配置目的:寄存器配置用于更改路由器启动过程。配置目的:寄存器配置用于更改路由器启动过程。启动位由4位16进制寄存器组成格式:0xA ... [详细]
author-avatar
laknm_456
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有