滑动验证码-elementui实现
使用elementui框架实现
html代码
<div class="button-center"><el-popoverplacement="top":width="imgWidth"title="安全验证"trigger="manual"v-model="popoverVisible"@hide="popoverHide"@show="popoverShow"><div class="z-popover"><!-- 滑块图片 --><canvas id="sliderImg"></canvas><!--背景图片--><canvas id="backgroundImg"></canvas><el-slider v-model="sliderValue" :show-tooltip="showTooltip" @input="sliderInput"@change="sliderChange" v-mousedown="sliderDown"></el-slider><el-divider></el-divider><i class="el-icon-circle-close z-el-popover-size" @click="popoverVisible = false"title="关闭"></i><i class="el-icon-refresh z-el-popover-size" @click="popoverShow"title="更换验证码"></i><span class="z-slider-result">{{sliderResult}}</span></div><el-button slot="reference" type="primary" @click="login()" :disabled="isDisabled"class="login-register-button-width">登录</el-button></el-popover></div>
主要代码:
function SliderImg(width, height, r, w) {this.width = width;this.height = height;this.r = r;this.w = w;// 使用双缓冲区去闪烁let getBufferCanvas = () => {// 创建隐藏Canvaslet buffer = document.createElement('canvas');buffer.width = this.width;buffer.height = this.height;buffer.ctx = buffer.getContext('2d');buffer.ctx.setTransform(1, 0, 0, 1, 0, 0);return buffer;}let init = () => {if (!this.backgroundImg || !this.sliderImg) {this.backgroundImg = document.getElementById("backgroundImg")this.backgroundImg.width = this.width;this.backgroundImg.height = this.height;this.backgroundImg.ctx = this.backgroundImg.getContext('2d');this.sliderImg = document.getElementById("sliderImg")this.sliderImg.width = this.width;this.sliderImg.height = this.height;this.sliderImg.ctx = this.sliderImg.getContext('2d');}this.sliderWidth = 2 * (this.r + this.w);$("#sliderImg").css('position', 'absolute').css("left", "0px");this.buffer1 = this.buffer1 == null ? getBufferCanvas() : this.buffer1;this.buffer2 = this.buffer2 == null ? getBufferCanvas() : this.buffer2;this.pos = getPos();}this.drawImg = function (src) {init();let img = new Image();img.src = src;img.onload = () => {drawBgBlock(img, this.buffer1.ctx);drawSiBlock(img, this.buffer2.ctx);}}let drawBgBlock = (img, ctx) => {ctx.clearRect(0, 0, this.width, this.height);ctx.drawImage(img, 0, 0, this.width, this.height);// 绘制滑块的形状drawBlock(ctx);ctx.fill();// 将缓冲区内容绘制到实际的画布中this.backgroundImg.ctx.clearRect(0, 0, this.width, this.height);this.backgroundImg.ctx.drawImage(this.buffer1, 0, 0, this.width, this.height);}let drawSiBlock = (img, ctx) => {ctx.clearRect(0, 0, this.width, this.height);ctx.drawImage(img, 0, 0, this.width, this.height);// 创建一个临时画布画一个圆, 然后将图片绘制上去, 形成一个滑块let tempCanvas = getBufferCanvas();tempCanvas.ctx.translate(-this.pos.siOffset, 0);drawBlock(tempCanvas.ctx);tempCanvas.ctx.clip();tempCanvas.ctx.drawImage(this.buffer2, 0, 0);// 将缓冲区内容绘制到实际的画布中this.sliderImg.ctx.clearRect(0, 0, this.width, this.height);this.sliderImg.ctx.drawImage(tempCanvas, 0, 0, this.width, this.height);}/*** 绘制缺口** @param ctx*/let drawBlock = (ctx) => {let x = this.pos.x, y = this.pos.y, r = this.pos.r, w = this.pos.w;ctx.beginPath();ctx.moveTo(x, y);// left// ctx.lineTo(x, y + w); 第一条直线可以省略, 下同理ctx.arc(x, y + w + r, r, -0.5 * Math.PI, 0.5 * Math.PI, false);ctx.lineTo(x, y + 2 * (w + r));// bottomctx.arc(x + w + r, y + 2 * (w + r), r, Math.PI, 0, true);ctx.lineTo(x + 2 * (w + r), y + 2 * (w + r));// rightctx.arc(x + 2 * (w + r), y + w + r, r, 0.5 * Math.PI, -0.5 * Math.PI, true);ctx.lineTo(x + 2 * (w + r), y);// topctx.arc(x + w + r, y, r, 0, Math.PI, false);ctx.lineTo(x, y);// 添加可见的效果ctx.lineWidth = 1;ctx.fillStyle = "rgba(255, 255, 255, 0.5)";ctx.strokeStyle = "rgba(255, 255, 255, 0.5)";ctx.stroke();// 和已有的图形进行异或操作ctx.globalCompositeOperation = "xor";}/*** 获取缺口坐标*/let getPos = () => {// 背景缺口的x轴坐标let x = getRandomNum(this.width / 2 + this.sliderWidth, this.width - 1.5 * this.sliderWidth);// 滑块的偏移量let siOffset = getRandomNum(0.45 * this.width, 0.55 * this.width);// 相同的y轴高度let y = getRandomNum(0.5 * this.sliderWidth, this.height - 1.5 * this.sliderWidth);return {x: x,y: y,r: this.r,w: this.w,siOffset: siOffset}}/*** 获取随机数** @param min* @param max* @returns {number}*/let getRandomNum = (min, max) => {return Math.floor(Math.random() * (max - min + 1) + min);}
}
事件方法
// 控制滑块移动
sliderInput(value) {if (this.sliderImg == null) {return;}// 移动的距离let moveLength = value * (this.imgWidth / 100)let start = this.sliderImg.pos.x - this.sliderImg.pos.siOffset;// 控制最大位置if (start + moveLength >= this.imgWidth) {this.sliderValue = value;} else {$("#sliderImg").css("left", moveLength);}
},// 鼠标按下时, 记录当下时间sliderDown() {this.startTime = new Date().getTime();},// 是否成功的判断sliderChange(value) {// 移动的距离let moveLength = value * (this.imgWidth / 100) - this.sliderImg.sliderWidth / 3// 偏移量let offset = this.sliderImg.pos.siOffset;// 允许的误差let mis = 5;// 成功的判断if (Math.abs(moveLength - offset) < mis) {let time = ((new Date().getTime() - this.startTime) / 1000.0).toFixed(2);switch (true) {case (time > 0 && time <= 1): {this.sliderResult = "只用了" + time + "s,快如闪电!"break;}case (time > 1 && time <= 2): {this.sliderResult = "用了" + time + "s,还不错!"break;}default: {this.sliderResult = "居然使用了" + time + "s,果然持久!"}}$(".z-slider-result").removeClass("z-slider-result-error").addClass("z-slider-result-success");// 后续成功的处理setTimeout(() => {this.loginForm.sliderCode = this.getSliderResult(time);}, 500);} else {this.sliderResult = "验证失败!"$(".z-slider-result").removeClass("z-slider-result-success").addClass("z-slider-result-error");this.popoverShow();}},
相关变量
// 以下时滑动图片验证码相关
sliderValue: 0, // 滑块的值
sliderResult: "", // 验证结果
showTooltip: false, // 隐藏tooltip
imgSrc: "/imgs/test2.png", // 图片的src
popoverVisible: false, // 验证框的显示和隐藏
imgWidth: 300, // 验证码图片的宽度
imgHeight: 120, // 验证码图片的高度
sliderImg: null, // 滑动图片验证码对象
startTime: 0, // 按下滑块的时间
使用示例:
if (this.sliderImg == null) {this.sliderImg = new SliderImg(this.imgWidth, this.imgHeight, 5, 10);
}
this.sliderImg.drawImg(this.imgSrc);
效果图

相关文章:
滑动验证码-elementui实现
使用elementui框架实现 html代码 <div class"button-center"><el-popoverplacement"top":width"imgWidth"title"安全验证"trigger"manual"v-model"popoverVisible"hide"popoverHide"show&quo…...
ubuntu 20.04 安装 高版本cuda 11.7 和 cudnn最新版
一、安装显卡驱动 参考另一篇文章:Ubuntu20.04安装Nvidia显卡驱动教程_ytusdc的博客-CSDN博客 二、安装CUDA 英伟达官网(最新版):CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer CUDA历史版本下载地址:C…...
svg图片如何渲染到页面,以及svg文件的上传
svg图片渲染到页面的几种方式 背景🟡require.context获取目录下的所有文件🟡方式1: 直接在html中渲染🟡方式: 发起ajax请求,获取SVG文件 背景 需要实现从本地目录下去获取所有的svg图标进行预览,将选中的图片显示在另…...
GPT-LLM-Trainer:如何使用自己的数据轻松快速地微调和训练LLM
一、前言 想要轻松快速地使用您自己的数据微调和培训大型语言模型(LLM)?我们知道训练大型语言模型具有挑战性并需要耗费大量计算资源,包括收集和优化数据集、确定合适的模型及编写训练代码等。今天我们将介绍一种实验性新方法&am…...
深入理解ForkJoin
任务类型 线程池执行的任务可以分为两种:CPU密集型任务和IO密集型任务。在实际的业务场景中,我们需要根据任务的类型来选择对应的策略,最终达到充分并合理地使用CPU和内存等资源,最大限度地提高程序性能的目的。 CPU密集型任务 …...
Spring5学习笔记—AOP编程
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Spring专栏 ✨特色专栏: M…...
适用于 Docker 用户的 kubectl
适用于 Docker 用户的 kubectl 你可以使用 Kubernetes 命令行工具 kubectl 与 API 服务器进行交互。如果你熟悉 Docker 命令行工具, 则使用 kubectl 非常简单。但是,Docker 命令和 kubectl 命令之间有一些区别。以下显示了 Docker 子命令, 并…...
网络安全设备篇——加密机
加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密,从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据,如金融信息、个人身份信息等。 加密机的主要功能包括: 数据加密:加密机使…...
Rust 基础入门 —— 2.3.所有权和借用
Rust 的最主要光芒: 内存安全 。 实现方式: 所有权系统。 写在前面的序言 因为我们这里实际讲述的内容是关于 内存安全的,所以我们最好先复习一下内存的知识。 然后我们,需要理解的就只有所有权概念,以及为了开发便…...
Node.js-Express框架基本使用
Express介绍 Express是基于 node.js 的web应用开发框架,是一个封装好的工具包,便于开发web应用(HTTP服务) Express基本使用 // 1.安装 npm i express // 2.导入 express 模块 const express require("express"); // 3…...
阿里云通用算力型u1云服务器CPU性能详细说明
阿里云服务器u1是通用算力型云服务器,CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器,通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)ÿ…...
设计模式之创建者模式
文章目录 一、介绍二、应用三、案例1. 麦当劳11随心配2. 代码演示3. 演示结果 四、优缺点五、送给读者 一、介绍 建造者模式(Builder Pattern)属于创建型设计模式,很多博客文章的对它的作用解释为用于将复杂对象的创建过程与其细节表示分离。但对于初学者来说&…...
Java之包,权限修饰符,final关键字详解
包 2.1 包 包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护。 在IDEA项目中,建包的操作如下: 包名的命名规范: 路径名.路径名.xxx.xxx // 例如ÿ…...
“深入解析JVM:Java虚拟机内部原理揭秘“
标题:深入解析JVM:Java虚拟机内部原理揭秘 摘要:本文将深入探讨Java虚拟机(JVM)的内部原理,包括JVM的架构、运行时数据区域、垃圾回收机制以及即时编译器等重要组成部分。通过对JVM内部原理的解析…...
Mac下Jmeter安装及基本使用
本篇文章只是简单的介绍下Jmeter的下载安装和最基本使用 1、初识Jmeter 前一段时间客户端app自测的过程中,有偶现请求某个接口返回数据为空的问题,领导让我循环100次请求这个接口,看看有没有结果为空的问题。听同事说有Jmeter的专业测试工具…...
云计算与边缘计算:加速数字化转型的关键驱动力
云计算和边缘计算技术正以惊人的速度改变着企业的业务和基础架构。这些先进的技术为企业带来了灵活性、可扩展性和成本效益的优势,重新定义了业务运作的方式。 云计算是通过互联网将计算资源提供给用户的一种服务模式。通过云计算,企业可以将应用程序、…...
TheGem主题 - 创意多用途和高性能WooCommerce WordPress主题/网站
TheGem主题概述 – 适合所有人的TheGem 作为设计元素、样式和功能的终极 Web 构建工具箱而设计和开发,TheGem主题将帮助您在几分钟内构建一个令人印象深刻的高性能网站,而无需触及一行代码。不要在编码上浪费时间,探索你的创造力!…...
Pytorch-day10-模型部署推理-checkpoint
模型部署&推理 模型部署模型推理 我们会将PyTorch训练好的模型转换为ONNX 格式,然后使用ONNX Runtime运行它进行推理 1、ONNX ONNX( Open Neural Network Exchange) 是 Facebook (现Meta) 和微软在2017年共同发布的,用于标准描述计算图的一种格式…...
vue使用websocket
建立websocket.js // 信息提示 import { Message } from element-ui // 引入用户id import { getTenantId, getAccessToken } from /utils/auth// websocket地址 var url ws://192.168.2.20:48081/websocket/message // websocket实例 var ws // 重连定时器实例 var tt // w…...
jmeter入门:接口压力测试全解析
一.对接口压力测试 1.配置 1.添加线程组(参数上文有解释 这里不介绍) 2.添加取样器 不用解释一看就知道填什么。。。 3.添加头信息(否则请求头对不上) 也不用解释。。。 4.配置监听器 可以尝试使用这几个监听器。 2.聚合结果…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
