当前位置: 首页 > 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.聚合结果…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...

快速排序算法改进:随机快排-荷兰国旗划分详解

随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...