使用npm包canvas在后端绘制一张背景图片,然后在这张背景图片中截取一部分作为拼图,让用户移动拼图到正确的位置,同时将此拼图所截取的区域用一个空白的区域覆盖。
import express from 'express';
const Canvas = require('canvas');
const path = require('path');
const router = express.Router();
// 背景图片的宽可以传参设置,默认值是320 * 180,小拼图默认是60 * 45
router.get('/drag_captcha', (req, res) => {
const { bgWidth: width } = req.query;
const bgWidth = parseInt(width) || 320;
const bgHeight = (width && parseInt(width * 180 / 320)) || 180;
const dragPicWidth = 60;
const dragPicHeight = 45;
const index = Math.floor(Math.random() * 13);
const positionX = Math.floor(Math.random() * (bgWidth - dragPicWidth - 10) + 11); // 空白拼图的定位X
const positionY = Math.floor(Math.random() * (bgHeight - dragPicHeight - 10) + 11);
const Image = Canvas.Image;
const bgCanvas = new Canvas(bgWidth, bgHeight);
const dragCanvas = new Canvas(dragPicWidth, dragPicHeight);
const background = bgCanvas.getContext('2d');
const dragPic = dragCanvas.getContext('2d');
const image = new Image();
image.onload = () => {
background.drawImage(image, 0, 0, 320, 180, 0, 0, bgWidth, bgHeight);
dragPic.drawImage(bgCanvas, positionX, positionY, dragPicWidth, dragPicHeight, 0, 0,
dragPicWidth, dragPicHeight);
background.clearRect(positionX, positionY, dragPicWidth, dragPicHeight);
};
image.src = path.join(__dirname, `../app/assets/images/validate/bg-${index}.png`);
if (req.session) {
req.session.dragCaptcha = {
positionX,
positionY
};
}
res.send({ bgCanvas: bgCanvas.toDataURL(), dragCanvas: dragCanvas.toDataURL() });
});
router.post('/check_captcha_position', (req, res) => {
const { offsetLeft, offsetTop } = req.body;
const { dragCaptcha = {} } = req.session;
const range = 5; // 误差范围
if (!offsetLeft || !offsetTop) return;
console.log(dragCaptcha.positionX, dragCaptcha.positionY);
const d