这是我参与更文挑战的第1天,活动详情查看:更文挑战
JS可以利用Canvas元素设计一些简单的图形,今天利用Canvas元素实现一个简易的图片验证码。设计过程和效果如下,不正之处,敬请指正。
(本文侧重于js,界面简陋,还望见谅)
总体思路
- 编写随机数生成函数和随机颜色生成函数
- 获取
Canvas
的2d
上下文 - 设计验证码生成函数
- 清除上轮验证码,设置
Canvas
背景 - 生成本轮验证码
- 随机确定每位验证码所在位置、颜色、阴影
- 使用
fill
画出验证码、使用translate
和rotate
随机确定验证码旋转角度 - 设计干扰线和干扰带点
- 随机确定干扰线数量、颜色、位置
- 随机确定干扰点数量、颜色、位置
- 将验证码生成函数通过
click
事件绑定在Canvas
上。
- 清除上轮验证码,设置
- 设计验证函数,验证用户数据是否正确
- 验证函数:判断是否验证成功,若成功输出成功信息,否则输出失败,并刷新验证码。
- 将验证函数通过
click
绑定在确定btn
中。
涉及基础知识
1.设计随机数生成函数
- 使用
Math.random
生成[0,1)
随机数。 - 使用
Math.floor
可以将某数向下取整
//value is 1
Math.floor(1.2);
// equal to below
Math.floor(1);
复制代码
随机数生成函数如下:
/* 返回一个随机数[minNum,maxNum] */
function randomNum(minNum,maxNum){
return Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum
}
/* 返回一个随机颜色[minNum,maxNum] */
function randomColor(minNum,maxNum){
return `rgba(${randomNum(minNum,maxNum)},${randomNum(minNum,maxNum)},${randomNum(minNum,maxNum)},0.8)`;
}
复制代码
2.DOM中设置、获取style
属性值
CSSStyleDeclaration
对象设置内联的style
DOM中有个
HTMLElement
类型,所有HTML
元素都是HTMLElement
或其子类型的实例。
HTMLElement
类型中包含一个style
属性,该属性类型为 CSSStyleDeclaration
,表示HTML
元素的内联style
属性<elem style="...">
,但不含样式表应用属性。 CSSStyleDeclaration
是只读的,但是可以通过CSSStyleDeclaration
属性设置HTML
样式。例如以下三种设置style
的方式:
//elt是`HTMLElement`类型的实例
// 方法一:在单个语句中设置多个样式,改变ele中所有内联样式
elt.style.cssText = "color: blue; border: 1px solid black";
// 方法二:使用HTMLElement中setAttribute方法,改变ele中所有内联样式
elt.setAttribute("style", "color:red; border: 1px solid blue;");
// 方法三:设置特定样式,同时保持其他内联样式值不变,
// 该设置等价于<elt style="background-color:blue;...">
//(本文中使用的方法)
elt.style.backgroundColor = "blue";
复制代码
CSSStyleDeclaration
对象的属性命名规则为小驼峰,比如css
中的background-color
属性,对应DOM CSSStyleDeclaration
对象的属性backgroundColor
。
使用Window.getComputedStyle()
获取所有style
样式
Window.getComputedStyle()
方法返回一个实时的 CSSStyleDeclaration 对象,当元素的样式更改时,它会自动更新本身。返回的 CSSStyleDeclaration 对象存储解析css
样式表后的属性值。
//Window.getComputedStyle()使用语法,其中pseudoElt指定一个要匹配的伪元素的字符串
let style = window.getComputedStyle(element, [pseudoElt]);
复制代码
//获取属性height,
let theCSSprop = window.getComputedStyle(elem,null).getPropertyValue("height");
复制代码
3.Canvas
的fill
方法簇和stroke
方法簇
2d上下文的两个基本操作为填充和描边,对应Canvas
元素的绘制方法为fill
方法簇和stroke
方法簇。
比如画个圆。使用stroke
方法效果如下(描边):
使用fill
方法效果如下(填充):
填充:fill
方法簇
fill
方法簇和stroke
方法簇中的方法基本一致,绘制图片验证码中需要使用fillText
方法绘制基本
- 填充矩形
fillRect
方法 - 填充文本
fillText
方法 - 填充路径
fill
方法
fill
方法簇有通用的fillStyle
属性确定填充的显示效果
描边:stroke
方法簇
- 填充矩形
strokeRect
方法 - 填充文本
strokeText
方法 - 填充路径
stroke
方法
stroke
方法簇有通用的strokeStyle
属性确定描边的显示效果
4.Canvas
的位移和旋转
2d上下文中支持常见的变换操作,变换的原点初始为(0,0)。
rotate(angle)
: 围绕原点把图形旋转angle
角度。translate(x,y)
: 将原点移动至(x,y)。
实现简易图片验证码
1.基本html框架
<div id="v_container" style="width: 200px;height: 50px;"></div>
<input type="text" id="code_input" value="" placeholder="请输入验证码"/><button id="my_button">验证</button>
复制代码
2.绘制4位验证码
/*绘制4位验证码*/
for(let i=4;i>0;i--){
/*设置验证码0-9*/
const num = randomNum(0,codeRef.length-1);
/*设置每个验证码的x,y坐标以及旋转角度*/
const x = (img.width / 5) * i+randomNum(-10,10);
code = num + code;
const y = randomNum(35,45);
const r = randomNum(-30,30) * Math.PI / 180;
/*注意顺序:先定原点,再旋转,否则出错*/
ctx.translate(x,y);
ctx.rotate(r);
/*通过fillStyle设置验证码样式,通过fillText绘制验证码*/
ctx.fillStyle = `rgba(${randomNum(10,50)},${randomNum(10,50)},${randomNum(10,50)},0.6)`;
ctx.font = `${randomNum(30,40)}px Arial`;
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur = 3;
ctx.shadowColor = "rgba(0,0,0,0.5)";
ctx.fillText(codeRef[num].toString(),0,0);
/*注意:设置好1位验证码后,撤销位移和旋转设置,否则出错*/
ctx.rotate(-1*r);
ctx.translate(-1*x,-1*y);
}
复制代码
3.绘制干扰线和干扰点
基本方法和绘制验证码一致
ctx.beginPath();
for(let i=0;i<randomNum(4,6);i++){
/*确定干扰线起点和终点坐标*/
startX = randomNum(0,img.width/2);
startY = randomNum(0,img.height);
endX = randomNum(img.width/2,img.width);
endY = randomNum(0,img.height);
/*使用stroke方法绘制干扰线*/
ctx.strokeStyle = `rgba(${randomNum(100,130)},${randomNum(100,130)},${randomNum(100,130)},${randomNum(0.3,0.9)})`;
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
}
for(let i=0;i<randomNum(10,20);i++){
/*确定干扰点坐标*/
x = randomNum(0,img.width);
y = randomNum(0,img.height);
/*使用fill方法绘制干扰点,注意干扰点要使用填充方式*/
ctx.fillStyle = `rgba(${randomNum(100,130)},${randomNum(100,130)},${randomNum(100,130)},${randomNum(0.3,0.9)})`;
ctx.moveTo(x,y);
/*通过arc方法绘制坐标为(0,0,),半径为1,起点角度为0度,终点角度为360度的圆形黑点(干扰点)*/
ctx.arc(x,y,1,0,2*Math.PI,false);
ctx.fill();
}
复制代码
4.绑定对应函数
图片验证码要求在页面加载时或点击图片时更新验证码,此外,需要在点击确认按钮时验证用户填入信息是否正确。
window.onload = changeVerifyCode;
img.addEventListener('click',changeVerifyCode);
btn.addEventListener('click',verify);
复制代码
写在最后
本文以Canvas
元素为出发点,通过js实现一个简易的图片验证码,希望对你在使用Canvas
绘图过程中有所启发。