使用 node-canvas 繪制驗證碼
最近要給 node 項目加上驗證碼,找到了 node-canvas 這個庫,簡單地用了一下,發現還是蠻好用的。
git 地址: node-canvas
顧名思義,node-canvas 允許你在 node 端使用 canvas。在驗證碼這個使用場景里,我們可以先生成驗證碼,然后在 canvas 上繪制,最后將圖片返回給前端。
step 1 安裝
在安裝 node-canvas 之前,還需要安裝一些依賴。不同的系統需要安裝的不同,以 linux 和 mac 為例:
-
linux: sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel
-
mac: brew install pkg-config cairo pango libpng jpeg giflib
安裝完依賴后,執行 npm install canvas 即可。
step 2 畫圖
通過獲取 canvas,可以得到 context 對象,然后就可以像在前端一樣繪制圖形了
const Canvas = require('canvas');
const canvas = new Canvas(100, 30),
ctx = canvas.getContext('2d');
實際上我用到的 api 和前端的 canvas 是一樣的,繪制過程就不多解釋,可以參考 canvas 的相關教程。
下面是繪制一個 a + b = ? 的驗證碼
ctx.font = '24px "Microsoft YaHei"';
// 繪制文本
let drawText = (text, x) => {
ctx.save();
// 旋轉角度
const angle = Math.random() / 10;
// y 坐標
const y = 22;
ctx.rotate(angle);
ctx.fillText(text, x, y);
ctx.restore();
}
// 隨機畫線
let drawLine = () => {
const num = Math.floor(Math.random() * 2 + 3);
// 隨機畫幾條彩色線條
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.lineTo(0, y1);
ctx.lineTo(width, y2);
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], 40);
drawText(numArr[Math.floor(Math.random() * numArr.length)][sec], 70);
drawText('=', 100);
drawText('?', 130);
// 驗證碼值的計算
let captcha;
switch(oper) {
case 0:
captcha = fir + sec;
break;
case 1:
captcha = fir - sec;
break;
case 2:
captcha = fir * sec;
break;
}
// 存入 session
req.session.captcha = captcha;
效果如下:
step 3 返回圖片
調用 canvas.toDataURL() ,可以返回圖片的 base64 格式數據。
res.send({
status: 200,
data: canvas.toDataURL()
})
前端將該數據加到 img 的 src 屬性中即可。
中文亂碼
在將項目部署到 linux 后,發現輸出顯示的圖片中的中文都變成了方框。
我參考了 redhat 6 下 node-canvas中文方框解決辦法 這篇文章,但是沒有全部運行,而是安裝了 yum groupinstall "Chinese Support" , yum groupinstall Fonts 這兩個。
另外參考 用node-canvas繪制中文的時候亂碼怎么解決? 問題里的 5 樓,使用了微軟雅黑。
還有 issue#461 ,在字體兩側加上引號。
我按這三個做了,然后 重啟項目 就好了~
來自:https://segmentfault.com/a/1190000007528623