uniapp微信小程序canvas画验证码

1. 效果

右侧验证码

2. 代码

1. html
<u-form-item label="验证码" prop="code" borderBottom :required="true">
		<u--input placeholder="验证码" v-model="form.code" border="none"></u--input>
		<image :src="canvasImgUrl" style="width: 140px;height: 80px;" @click="updateImageCode">		</image>
</u-form-item>

<canvas style="position: fixed;left: -100000px;280rpx;height: 140rpx;" canvas-id="canvas"></canvas>
2. script
1. data
import { createCanvas, validateCode } from '../../common/createCanvas.js';
	export default {
		data() {
			return {
				canvasImgUrl: '',
				rules: { // 表单校验
					// 验证码规则
					'code': [
						{
							type: 'string',
							required: true,
							message: '请输入验证码',
							trigger: ['blur', 'change']
						},
						{
							// 自定义验证函数
							validator: (rule, value, callback) => {
								// let validate = this.mcaptcha.validate(value)
								let validate = validateCode(value);
								if(validate) {
									return true
								}
								callback(new Error('验证码错误'));
							},
						}
					],
				},
			}
		},
2. onReady
onReady() {
			this.$refs.form.setRules(this.rules);
			createCanvas({
				el: 'canvas',
				width: 140,
				height: 80,
				createCodeImg: "",
			}, this).then(res => {
				this.canvasImgUrl = res;
				console.log('绘画')
			})
		},
3. methods
methods: {
			// 刷新验证码
			updateImageCode() {
			  // this.mcaptcha.refresh();
				createCanvas({
					el: 'canvas',
					width: 140,
					height: 80,
					createCodeImg: "",
				}, this).then(res => {
					this.canvasImgUrl = res;
					console.log('绘画')
				})
			},
		} 
3. 画验证码公共方法 utils.js
import { deepCopy } from '../common/utils.js'
/** 重要事件分享图绘制
 * @param {Object} option 参数
 * @param {Object} this   上下文
 * @param {Object} el canvasid
 * @param {Object} createCodeImg 随机四位数
 */
let getOptions;
export function createCanvas(options) {
	return new Promise(function(resolve, reject) {
		let fontSize = options.height * 3 / 6;
		let ctx = uni.createCanvasContext(options.el, this);
		ctx.setTextBaseline("middle");
		ctx.setFillStyle(randomColor(180, 240));
		//生成随机数
		var code = '';
		var txtArr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q','r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O','P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',0,1,2,3,4,5,6,7,8,9]
		for(var i=0;i<4;i++){
		  code += txtArr[randomNum(0, txtArr.length)];
		}
		options.createCodeImg = code;
		let arr = (code + '').split('');
		if (arr.length === 0) {
		  arr = ['e', 'r', 'r','o','r'];
		};
		let offsetLeft = options.width * 0.6 / (arr.length - 1);
		let marginLeft = options.width * 0.2;
		arr.forEach((item, index) => {
		  ctx.setFillStyle(randomColor(0, 180));
		  let size = randomNum(32, fontSize);
		  ctx.setFontSize(size);
		  let dis = offsetLeft * index + marginLeft - size * 0.3;
		  let deg = randomNum(-30, 30);
		  ctx.translate(dis, options.height*0.5);
		  ctx.rotate(deg * Math.PI / 180);
		  ctx.fillText(item, 0, 0);
		  ctx.rotate(-deg * Math.PI / 180);
		  ctx.translate(-dis, -options.height * 0.5);
		})
		for (var i = 0; i < 4; i++) {
		  ctx.strokeStyle = randomColor(40, 180);
		  ctx.beginPath();
		  ctx.moveTo(randomNum(0, options.width), randomNum(0,options.height));
		  ctx.lineTo(randomNum(0, options.width), randomNum(0, options.height));
		  ctx.stroke();
		}
		for (var i = 0; i < options.width / 4; i++) {
		  ctx.fillStyle = randomColor(0, 255);
		  ctx.beginPath();
		  ctx.arc(randomNum(0, options.width), randomNum(0, options.height), 1, 0, 2 * Math.PI);
		  ctx.fill();
		}
		
		ctx.save();
		
		// 获取系统信息
		const result = uni.getSystemInfoSync();
		const platform = result.platform;
		let time = 0;
		if (platform === 'android') {
			// 在安卓平台,如果海报过于复杂在转换时需要做延时,否则样式会错乱
			time = 300;
		}
		// this.ctx.draw();
		getOptions = deepCopy(options);
		ctx.draw(false, function() {
			setTimeout(function() {
				//将canvas转换成临时图片文件
				wx.canvasToTempFilePath({
					width: '140',
					height: '70',
					canvasId: options.el,
					fileType: 'png',
					success(res) {
						console.log('生成成功');
						console.log(res.tempFilePath, '111');
						resolve(res.tempFilePath);
					},
					fail(err) {
						console.log('生成失败');
						console.log('canvasToTempFilePath err', err);
						reject(err);
					},
					complete() {
						console.log('成功、失败都走的回调');
					}
				}, this);
			}, time);
		});
	})
}

export function validateCode(code) {
	var code = code.toLowerCase();
	var v_code = getOptions.createCodeImg.toLowerCase();
	if (code == v_code.substring(v_code.length - 4)) {
		return true;
	} else {
		return false;
	}
}

function randomNum(min, max) {
	return Math.floor(Math.random() * (max - min) + min);
}

function randomColor(min, max) {
	let r = randomNum(min, max);
	let g = randomNum(min, max);
	let b = randomNum(min, max);
	return "rgb(" + r + "," + g + "," + b + ")";
}


deepCopy为深拷贝

猜你喜欢

转载自blog.csdn.net/honeymoon_/article/details/130075330