当前位置: 首页 > news >正文

滑动验证码-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最新版

一、安装显卡驱动 参考另一篇文章&#xff1a;Ubuntu20.04安装Nvidia显卡驱动教程_ytusdc的博客-CSDN博客 二、安装CUDA 英伟达官网&#xff08;最新版&#xff09;&#xff1a;CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer CUDA历史版本下载地址&#xff1a;C…...

svg图片如何渲染到页面,以及svg文件的上传

svg图片渲染到页面的几种方式 背景&#x1f7e1;require.context获取目录下的所有文件&#x1f7e1;方式1: 直接在html中渲染&#x1f7e1;方式: 发起ajax请求&#xff0c;获取SVG文件 背景 需要实现从本地目录下去获取所有的svg图标进行预览&#xff0c;将选中的图片显示在另…...

GPT-LLM-Trainer:如何使用自己的数据轻松快速地微调和训练LLM

一、前言 想要轻松快速地使用您自己的数据微调和培训大型语言模型&#xff08;LLM&#xff09;&#xff1f;我们知道训练大型语言模型具有挑战性并需要耗费大量计算资源&#xff0c;包括收集和优化数据集、确定合适的模型及编写训练代码等。今天我们将介绍一种实验性新方法&am…...

深入理解ForkJoin

任务类型 线程池执行的任务可以分为两种&#xff1a;CPU密集型任务和IO密集型任务。在实际的业务场景中&#xff0c;我们需要根据任务的类型来选择对应的策略&#xff0c;最终达到充分并合理地使用CPU和内存等资源&#xff0c;最大限度地提高程序性能的目的。 CPU密集型任务 …...

Spring5学习笔记—AOP编程

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Spring专栏 ✨特色专栏&#xff1a; M…...

适用于 Docker 用户的 kubectl

适用于 Docker 用户的 kubectl 你可以使用 Kubernetes 命令行工具 kubectl 与 API 服务器进行交互。如果你熟悉 Docker 命令行工具&#xff0c; 则使用 kubectl 非常简单。但是&#xff0c;Docker 命令和 kubectl 命令之间有一些区别。以下显示了 Docker 子命令&#xff0c; 并…...

网络安全设备篇——加密机

加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密&#xff0c;从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据&#xff0c;如金融信息、个人身份信息等。 加密机的主要功能包括&#xff1a; 数据加密&#xff1a;加密机使…...

Rust 基础入门 —— 2.3.所有权和借用

Rust 的最主要光芒&#xff1a; 内存安全 。 实现方式&#xff1a; 所有权系统。 写在前面的序言 因为我们这里实际讲述的内容是关于 内存安全的&#xff0c;所以我们最好先复习一下内存的知识。 然后我们&#xff0c;需要理解的就只有所有权概念&#xff0c;以及为了开发便…...

Node.js-Express框架基本使用

Express介绍 Express是基于 node.js 的web应用开发框架&#xff0c;是一个封装好的工具包&#xff0c;便于开发web应用&#xff08;HTTP服务&#xff09; Express基本使用 // 1.安装 npm i express // 2.导入 express 模块 const express require("express"); // 3…...

阿里云通用算力型u1云服务器CPU性能详细说明

​阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff…...

设计模式之创建者模式

文章目录 一、介绍二、应用三、案例1. 麦当劳11随心配2. 代码演示3. 演示结果 四、优缺点五、送给读者 一、介绍 建造者模式(Builder Pattern)属于创建型设计模式&#xff0c;很多博客文章的对它的作用解释为用于将复杂对象的创建过程与其细节表示分离。但对于初学者来说&…...

Java之包,权限修饰符,final关键字详解

包 2.1 包 包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术&#xff0c;不同的技术类放在不同的包下&#xff0c;方便管理和维护。 在IDEA项目中&#xff0c;建包的操作如下&#xff1a; 包名的命名规范&#xff1a; 路径名.路径名.xxx.xxx // 例如&#xff…...

“深入解析JVM:Java虚拟机内部原理揭秘“

标题&#xff1a;深入解析JVM&#xff1a;Java虚拟机内部原理揭秘 摘要&#xff1a;本文将深入探讨Java虚拟机&#xff08;JVM&#xff09;的内部原理&#xff0c;包括JVM的架构、运行时数据区域、垃圾回收机制以及即时编译器等重要组成部分。通过对JVM内部原理的解析&#xf…...

Mac下Jmeter安装及基本使用

本篇文章只是简单的介绍下Jmeter的下载安装和最基本使用 1、初识Jmeter 前一段时间客户端app自测的过程中&#xff0c;有偶现请求某个接口返回数据为空的问题&#xff0c;领导让我循环100次请求这个接口&#xff0c;看看有没有结果为空的问题。听同事说有Jmeter的专业测试工具…...

云计算与边缘计算:加速数字化转型的关键驱动力

云计算和边缘计算技术正以惊人的速度改变着企业的业务和基础架构。这些先进的技术为企业带来了灵活性、可扩展性和成本效益的优势&#xff0c;重新定义了业务运作的方式。 云计算是通过互联网将计算资源提供给用户的一种服务模式。通过云计算&#xff0c;企业可以将应用程序、…...

TheGem主题 - 创意多用途和高性能WooCommerce WordPress主题/网站

TheGem主题概述 – 适合所有人的TheGem 作为设计元素、样式和功能的终极 Web 构建工具箱而设计和开发&#xff0c;TheGem主题将帮助您在几分钟内构建一个令人印象深刻的高性能网站&#xff0c;而无需触及一行代码。不要在编码上浪费时间&#xff0c;探索你的创造力&#xff01…...

Pytorch-day10-模型部署推理-checkpoint

模型部署&推理 模型部署模型推理 我们会将PyTorch训练好的模型转换为ONNX 格式&#xff0c;然后使用ONNX Runtime运行它进行推理 1、ONNX ONNX( Open Neural Network Exchange) 是 Facebook (现Meta) 和微软在2017年共同发布的&#xff0c;用于标准描述计算图的一种格式…...

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.添加线程组&#xff08;参数上文有解释 这里不介绍&#xff09; 2.添加取样器 不用解释一看就知道填什么。。。 3.添加头信息&#xff08;否则请求头对不上&#xff09; 也不用解释。。。 4.配置监听器 可以尝试使用这几个监听器。 2.聚合结果…...

如何高效使用Xtreme Download Manager:免费开源下载加速器完全指南

如何高效使用Xtreme Download Manager&#xff1a;免费开源下载加速器完全指南 【免费下载链接】xdm Powerfull download accelerator and video downloader 项目地址: https://gitcode.com/gh_mirrors/xd/xdm Xtreme Download Manager&#xff08;简称XDM&#xff09;是…...

基于Xilinx的FPGA在线升级程序(仅7系列及以上支持)

基于xilinx的FPGA在线升级程序&#xff0c;仅7系列以上支持一、模块概述 本文档详细解读的decalperebotsdeenpotpidehcac_xnilix模块&#xff0c;是Xilinx 7系列FPGA&#xff08;具体型号xc7k325tffg900-2&#xff09;在线升级系统中的核心调试枢纽组件。该模块基于Vivado 2020…...

NAS+Docker+PostgreSQL:打造全平台同步的私有Joplin笔记服务器

1. 为什么选择私有化部署Joplin笔记服务 每次打开印象笔记时弹出的会员订阅弹窗&#xff0c;或是发现OneDrive同步又卡在某个小文件时&#xff0c;相信很多朋友都动过自建笔记服务的念头。三年前我也被这些问题困扰&#xff0c;直到在GitHub上发现了这个宝藏项目——Joplin&…...

Local Moondream2实操手册:上传图片即获详细描述的全流程

Local Moondream2实操手册&#xff1a;上传图片即获详细描述的全流程 想让你的电脑学会“看图说话”吗&#xff1f;今天我们来聊聊一个特别有意思的工具——Local Moondream2。简单来说&#xff0c;它就像给你的电脑装上了一双智能的眼睛和一个能说会道的嘴巴。你给它一张图片…...

奇异值分解之 Courant-Fischer 定理的几何直观与子空间极值解释

1. 从几何视角理解Courant-Fischer定理 第一次接触Courant-Fischer定理时&#xff0c;我被那些"极大极小"和"极小极大"的表述绕得头晕。直到有一天&#xff0c;我尝试用几何图形来理解它&#xff0c;突然就豁然开朗了。想象你手里握着一个弹性橡皮筋&#…...

你的终端神器之Oh My Zsh扰

1.安装环境准备 1.1.查看物理内存 [rootaiserver ~]# free -m 1.2.操作系统版本 [rootaiserver ~]# cat /etc/redhat-release 1.3.操作系统内存 [rootaiserver ~]# df -h /dev/shm/ 1.4.磁盘空间 [rootaiserver ~]# df -TH [rootaiserver ~]# df -h /tmp/ [rootaiserver ~]# d…...

MySQL Binlog 文件同步流程解析

MySQL Binlog文件同步流程解析 在分布式系统与数据库高可用架构中&#xff0c;MySQL的Binlog&#xff08;二进制日志&#xff09;文件同步是实现数据一致性与实时复制的核心技术。Binlog记录了数据库的所有变更操作&#xff0c;通过解析和传输这些日志&#xff0c;可以实现主从…...

L6599A VCO工作原理深度解析:为什么你的LLC闭环仿真总是不稳定?

L6599A VCO工作原理深度解析&#xff1a;为什么你的LLC闭环仿真总是不稳定&#xff1f; 在LLC谐振变换器的设计中&#xff0c;闭环仿真的稳定性往往是工程师面临的最大挑战之一。许多经验丰富的电源工程师都曾遇到过这样的困境&#xff1a;明明按照芯片手册设计了所有外围电路&…...

ADS1220_WE库详解:工业级24位ADC驱动与高精度传感器采集实现

1. ADS1220_WE 库深度技术解析&#xff1a;面向工业级高精度采集的 24 位四通道 ADC 驱动实现1.1 芯片级定位与工程价值ADS1220 是德州仪器&#xff08;TI&#xff09;推出的低功耗、高精度、24 位 Δ-Σ 型模数转换器&#xff0c;专为工业传感器信号调理场景设计。其核心价值不…...

Foxmail添加Gmail账号保姆级教程:如何绕过两步验证直接配置(2024最新版)

Foxmail高效配置Gmail全攻略&#xff1a;2024专属密码解决方案 每次登录Gmail都要反复输入验证码&#xff1f;Foxmail里添加Gmail账户总提示密码错误&#xff1f;这可能是2024年最让你抓狂的办公效率杀手之一。作为深度邮件使用者&#xff0c;我完全理解那种每天要处理十几个邮…...