1、在安装 node-canvas 之前,还需要安装一些依赖。不同的系统需要安装的不同,以 linux 为例:
-
linux:
sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel
-
安装完依赖后,执行
npm install canvas
即可
2、给linux 安装字体库因为图片验证码可能需要使用中文字体
- 使用yum -y install fontconfig安装fontconfig,通过fontconfig来安装字体库,安装前可以查看有没有安装,安装成功后在/usr/shared目录就可以看到fonts和fontconfig目录了
- 添加中文字体,可以在win7 c:/windows/fonts 文件夹中复制到linux 服务器,或者从网上下载(win7字体库下载),下载完后,在/usr/shared/fonts文件夹下新建一个文件夹,文件夹名称随意,如:ChineseFonts,然后将ttf格式的字体文件复制到该目录下并且修改文件夹的权限,hmod -R 755 /usr/share/fonts/ChineseFonts
- 安装ttmkfdir来搜索目录中所有的字体信息,并汇总生成fonts.scale文件,输入命令:yum -y install ttmkfdir,然后执行ttmkfdir命令:ttmkfdir-e /usr/share/fonts/encodings/encodings.dir,最后一步就是修改字体配置文件了,首先通过编辑器打开配置文件:vi /etc/fonts/fonts.conf,将<dir>/usr/share/fonts/ChineseFonts</dir> 加入到Font directory list 中,然后输入:wq保存退出,最后别忘了刷新内存中的字体缓存,命令:fc-cache,通过命令:fc -list 就可以看到多有的字体列表
3、代码如下:
//产生随机数
var rn=function(min,max){
return parseInt(Math.random()*(max-min)+min);
}
//产生随机颜色
var rc=function (min,max){
var r=rn(min,max);
var g=rn(min,max);
var b=rn(min,max);
return `rgb(${r},${g},${b})`;
}
//画布
const canvas = new Canvas(100, 30),
ctx = canvas.getContext('2d');
ctx.font = '16px "Microsoft YaHei"';
let height=30,width=100;
// 绘制文本
let drawText = (text, x) => {
ctx.save();
// 旋转角度
const angle = Math.random() / 10;
//字体颜色
ctx.fillStyle=rc(10,120);
ctx.save();
// y 坐标
const y = 22;
ctx.rotate(angle);
ctx.fillText(text, x, y);
ctx.restore();
}
// 随机画线
let drawLine = () => {
const num = Math.floor(Math.random() * 2 + 5);
// 随机画几条彩色线条
for (let i = 0; i < num; i++) {
const color = '#' + (Math.random() * 0xffffff << 0).toString(16);
const y1 = Math.random() * height;
const y2 = Math.random() * height;
// 画线
ctx.strokeStyle = color;
ctx.beginPath();
//随机位置长度
ctx.moveTo(Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height));
ctx.lineTo(Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height));
ctx.lineWidth = 1;
ctx.stroke();
}
}
// 数字的文本随机从小写汉字、大写汉字、数字里选择
const numArr = [
'〇一二三四五六七八九',
'0123456789',
'零壹贰叁肆伍陆柒捌玖'
];
// 第一个数字
const fir = Math.floor(Math.random() * 10);
// 第二个数字
const sec = Math.floor(Math.random() * 10);
// 随机选取运算
const operArr = ['加', '减', '乘'];
const oper = Math.floor(Math.random() * operArr.length);
drawLine();
//最后的数字是文本的横坐标
drawText(numArr[Math.floor(Math.random() * numArr.length)][fir], 10);
drawText(operArr[oper], 28);
drawText(numArr[Math.floor(Math.random() * numArr.length)][sec], 50);
drawText('=', 72);
drawText('?', 90);
//随机产生60个干扰的小点
for(var i=0;i<60;i++){
ctx.beginPath();
ctx.arc(rn(0,width),rn(0,height),1,0,2*Math.PI);
ctx.closePath();
ctx.fillStyle=rc(150,200);
ctx.fill();
}
// 验证码值的计算,并将captcha的保存到session或者redis中
let captcha;
switch(oper) {
case 0:
captcha = fir + sec;
break;
case 1:
captcha = fir - sec;
break;
case 2:
captcha = fir * sec;
break;
}
最后以base64的格式输出 var images= canvas.toDataURL();把images的值发送给前段,直接把值赋给<img src="">表签中的src
如图: