在 uni-app 中使用 canvas 绘制验证码图片或者纯数字验证吗

在 uni-app 中使用 canvas 绘制验证码图片与在 Web 中使用 HTML5 canvas 类似,但 uni-app 提供了一套跨平台的 API,使得开发者可以在不同平台上使用相同的代码。以下是一个基本的示例,展示如何在 uni-app 中使用 canvas 绘制一个简单的验证码图片。

首先,你需要在页面的 .vue 文件中添加一个 <canvas> 标签,并为其指定一个 ref 或者 id,以便在 JavaScript 中引用它。

效果图:

组件代码:

<template>  
  <view v-if="visible" class="captcha-modal">   
	<view class="captcha-container">
	  <text class="close" @click="close">×</text>
	  <text class="captcha-text"> 校验码 </text>  
	  <!-- 纯数字验证码 -->
	  <!-- <text class="captcha-value">{{ captcha }}</text>  -->
	  
	  <view class="captcha-value-view">
		  <canvas class="captcha-value-image" canvas-id="captchaCanvas"></canvas>
	  </view>
	  
	  <view class="captcha-view">
		  <input  class="input-captcha" type="text" v-model="userInput" placeholder="请输入" @confirm="checkCaptcha" />  
		  <!-- <button class="captcha-btn" @click="generateCaptcha">刷新</button> -->
          <button class="cu-btn" @click="generateCaptcha">刷新</button>
		  
	  </view>
	   
	  <button class="check-btn" @click="checkCaptcha">校验</button>  
	  <text   class="error-message" v-if="errorMessage" >{{ errorMessage }}</text>  
	</view>  
  </view>  
</template>  
  
<script>  
export default {  
  name: 'CaptchaPage',  
  emits: ['success'],

  props: {  
    visible: {  
      type: Boolean,  
      default: false  
    }  
  },  
  data() {  
    return {  
      captcha: '',  
      userInput: '',  
      errorMessage: ''  
    };  
  },  
  watch: {  
    // 监听visible变化,如果变为true则生成验证码  
    visible(newVal) {  
      if (newVal) {  
		
		 setTimeout(() => {  
			 this.generateCaptcha();
			 this.userInput = '';  
			 this.errorMessage = '';  
		  }, 500); // 延迟 500 毫秒     
      }  
    }  
  }, 
   
  methods: {  
	generateCaptcha() {  
	      const ctx = uni.createCanvasContext('captchaCanvas', this); // 创建 canvas 绘图上下文  
	  
	      // 设置背景色  
	      ctx.setFillStyle('#ffffff');  
	      ctx.fillRect(0, 0, 100, 40);  
	  
	      // 随机生成验证码字符串  
	      const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';  
	      let captchaText = '';  
	      for (let i = 0; i < 4; i++) {  
	        captchaText += chars.charAt(Math.floor(Math.random() * chars.length));  
	      }  
	  
	     // 更新组件的 captchaText 数据  
	     this.captcha = captchaText; 
		 this.userInput = '';
		 this.errorMessage = '';  
		 
	      // 设置字体样式  
	      ctx.setFontSize(28);  
	      ctx.setFillStyle('#333333');  
	      ctx.setTextAlign('center');  
	  
	      // 绘制验证码文本  
	      ctx.fillText(captchaText, 50, 30); // 文本绘制在中心点  
	  
	      // 绘制干扰线  
	      for (let i = 0; i < 3; i++) {  
	        ctx.beginPath();  
	        ctx.setStrokeStyle('rgba(0,0,0,' + Math.random() * 0.5 + ')');  
	        ctx.moveTo(Math.random() * 100, Math.random() * 40);  
	        ctx.lineTo(Math.random() * 100, Math.random() * 40);  
	        ctx.stroke();  
	      }  
	  
	      // 绘制干扰点  
	      for (let i = 0; i < 100; i++) {  
	        ctx.fillStyle = 'rgba(0,0,0,' + Math.random() * 0.3 + ')';  
	        ctx.beginPath();  
	        ctx.arc(Math.random() * 100, Math.random() * 40, 1, 0, 2 * Math.PI);  
	        ctx.fill();  
	      }  
	  
	      // 将绘制的内容导出到 canvas 显示  
	      ctx.draw(true); // 这里的 true 表示绘制完成后执行回调  
	    },
	
	
	
	/* 纯数字验证码
	 generateCaptcha() {  
	   this.captcha = Math.floor(100000 + Math.random() * 900000).toString(); 
	   this.userInput = '';
	   this.errorMessage = '';  
	 }, 
	*/ 
    checkCaptcha() {  
	  if (this.userInput.toLowerCase() === this.captcha.toLowerCase()) {  
        this.$emit('success','Y'); // 验证码正确时关闭验证码,向父组件发出success事件  
      } else {  
        this.errorMessage = '验证码错误,请重试。';  
      }  
    },  
    close() { 
	  this.$emit('success',"N"); // 关闭验证码,向父组件发出success事件
	}  
  }  
};  
</script>  
  
<style scoped>  
.captcha-modal {  
  position: fixed;  
  top: 0;  
  left: 0;  
  right: 0;  
  bottom: 0;  
  background-color: rgba(0, 0, 0, 0.5);  
  display: flex;  
  justify-content: center;  
  align-items: center;  
}  
.captcha-container {  
  background-color: #fff;  
  border-radius: 8px;  
  padding: 20px;  
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);  
  width: 80%;  
  max-width: 400px;  
  text-align: center;  
}  
  
.captcha-text {  
  font-size: 16px;  
  color: #333;  
  margin-bottom: 10px;  
}  

.captcha-value {  
  font-size: 24px;  
  color: #f44336;  
  margin-bottom: 20px;  
}
.captcha-value-view{
	display: flex;
	justify-content: center;  
	align-items: center; 
	padding-top: 10px;
}
.captcha-value-image {  
  width: 100px; 
  height: 40px;  
  background-color: rgba(0, 0, 0, 0.1); 
}
  
.captcha-view{
   display: flex; /* 启用Flex布局 */  
    flex-direction: row; /* 设置主轴方向为水平方向 */  
    align-items: center; /* 子元素在交叉轴上的对齐方式,这里设置为居中 */  
    justify-content: space-between; /* 子元素在主轴上的对齐方式,这里设置为两端对齐 */  
    padding:10px 0px 10px 0px; /* 内边距 */
}
.input-captcha {  
    flex: 1; /* 弹性布局,让输入框占据剩余空间 */  
    margin-right: 10px; /* 右边距,用于与按钮隔开一定距离 */
	left: 0px;
    padding: 8px; /* 内边距 */  
    border: 1px solid #ccc; /* 边框 */  
    border-radius: 4px; /* 边框圆角 */ 
    height: 40px;
    font-size: 18px;  
} 
  
/* 设置占位符的文字样式 没有生效 */  
.input-captcha::placeholder {  
  color: #999; /* 占位符文字颜色,可按需设置 */  
  font-size: 16px; /* 占位符文字大小 */  
} 
.captcha-btn {  
    padding: 0px 20px; /* 内边距 */  
    background-color: #0081ff; /* 背景色 */  
    color: white; /* 文字颜色 */  
    border: none; /* 去除边框 */  
    border-radius: 4px; /* 边框圆角 */ 	
	height: 40px;
	font-size: 16px;  

}  
  
.check-btn {  
  margin-top: 10px;
  padding: 0px 20px;
  line-height: 45px;
  background-color: #0081ff;  
  color: white;  
  border: none;  
  border-radius: 4px;  
  cursor: pointer;
}  
  
.close {  
  position: absolute;  
  top: 10px;  
  right: 15px;  
  font-size: 34px;  
  color: #aaa;  
  cursor: pointer;  
} 
.error-message {  
  display: inline-block; /* 或 block,根据需要选择 */  
  height: 30px; /* 设置高度,但注意这通常不会有任何效果,因为文本内容会溢出 */ 
  color: red;  
  line-height: 30px; /* 可以通过设置行高来垂直居中文本(如果高度固定的话) */  
  font-size: 14px;
}    
</style>

父组件代码

		   <CaptchaPage :visible="showCaptchaModal" @success="onCaptchaSuccess" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值