参考连接:
https://www.cnblogs.com/qxxblogs/p/12388482.html

https://www.cnblogs.com/knuzy/p/9993181.html

https://www.cnblogs.com/527xyz/p/13435353.html

https://blog.csdn.net/yyjourney/article/details/79072093

vue项目前端实现图形验证码

1.设置整个页面为蓝色

在样式中将body设置为蓝色

<style>
	body{
		/* background-color: 'url('+requird('../../assets/img')+')'; */
		
		background-color: blue;
		
	}
</style>

2.将图片设为背景

方法一:(不好控制图片的属性设置)

<style>
body{
		/* 将图片设为背景 */
		background-image: url(../../assets/img/2.jpg) ;
		/* 将图片设为不平铺 */
		background-repeat: no-repeat;
}
body .login{
	/* 设置背景图片大小 ,相对于body为100%*/
	background-size: 100% 100%;
	/* background: rgba(34,34,34,0.5); */
}

方法二(优选):

<template>
	<!-- 存放背景图片 -->
	<div class="background">
		<!-- img中的宽高设置图像尺寸,宽高100%是为了让整个图像显示在页面 -->
		<img :src="imgSrc" width="100%" height="100%" />
	</div>
	<!-- 存放登录表单 -->
	<!-- <div class="front">
		<p>登录:<input type="text" name="lo" /></p>
		<p>注册:<input type="text" name="re" /></p>
	</div> -->
</template>

<script>
	export default{
		data(){
			return{
				imgSrc:require('../../assets/img/2.jpg')
			}
		}
	}
</script>

<style>
	.background{
		/* 宽高100%是为了铺满屏幕 */
		width: 100%;
		height: 100%;
		/* z-index用来确定层叠关系,值大的显示在值小的上面 */
		z-index: -1;
		position: absolute;
		/* 调节背景图片透明度 */
		opacity: 0.3;
	}
	
</style>

效果图:
在这里插入图片描述

3.在背景图的基础上添加一个登录框

(1)使用el-input组件时,
①v-model属性一定要存在,不然会出现无法输入的问题
②通过placeholder将文字显示出来
③通过prefix-icon="el-icon-phone"在输入框前面添加图标
④通过style="width: 250px;"设置输入框的长度
(2)将某个块设置为中心位置
top、left是以左上角为原点,因此平移以后不处于中心位置
加上translate(-50%, -50%)的作用是,往上(x轴),左(y轴)移动自身长宽的50%,因此就可以居于中心位置了

	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);

(3)只设置背景颜色透明度可以使用rgba

background: rgba(34,34,34,0.1);	

在这里插入图片描述

完整登录页面

1.效果:
在这里插入图片描述
在这里插入图片描述

2.项目目录
在这里插入图片描述

1.userlogin.vue

<template>
	<div class="app">
		<!-- 存放背景图片 -->
		<div class="background">
			<!-- img中的宽高设置图像尺寸,宽高100%是为了让整个图像显示在页面 -->
			<img :src="imgSrc" width="100%" height="100%" />
		</div>
		<!-- 存放登录表单 -->
		<div class="front">
			<!-- 通过placeholder将文字显示出来 -->
			<div class="tu">
				<p><el-input type="tel"  style="width: 250px;"  placeholder="请输入用户手机号"  v-model="tel" prefix-icon="el-icon-phone" /></p>
				<p><el-input type="text" style="width: 250px;" placeholder="请输入用户密码"  prefix-icon="el-icon-star-off" v-model="password"></el-input></p>
				<p>				
					<div class="get-code" @click="refreshCode()">
						<el-input type="text"  style="width: 125px;" placeholder="图形验证码"  v-model="ma" prefix-icon="el-icon-picture-outline"/>
					    <s-identify class="get-code1" :identifyCode="identifyCode"></s-identify>
					</div>
				</p>
				<p>
					<el-button type="primary" plain>登录</el-button>
					<router-link class="r" to="/re">立即注册</router-link>
					<router-view></router-view>
					<!-- router-view属性的位置决定是在新页面在该页面的上面还是下面 -->
				</p>
			</div>
		</div>
		
	</div>
	
	
</template>

<script>
	// 导入生成图形码的文件
	import SIdentify from "../../components/sIdentify.vue"
	export default{
		
		components:{
			SIdentify,		
		},
		data(){
			return{
				
				imgSrc:require('../../assets/img/2.jpg'),
				password:'',
				tel:'',
				ma:'',
				identifyCode: "",
				identifyCodes: "0123456789abcdwerwshdjeJKDHRJHKOOPLMKQ",
			}
		},
		 methods: {            
		           refreshCode() {//
		             this.identifyCode = "";
		             this.makeCode(this.identifyCodes,4);
		           },
		           randomNum (min, max) {
		             max = max + 1
		             return Math.floor(Math.random() * (max - min) + min)
		           },
		           // 随机生成验证码字符串
		           makeCode (data, len) {
		             for (let i = 0; i < len; i++) {
		             this.identifyCode += data[this.randomNum(0, data.length - 1)]
		           }
		        }
				
		    }
		
	}
</script>

<style>
	
	.background{
		
		/* 宽高100%是为了铺满屏幕 */
		width: 100%;
		height: 100%;
		/* z-index用来确定层叠关系,值大的显示在值小的上面 */
		z-index: -1;
		position: absolute;
		/* 调节背景图片透明度 */
		opacity: 0.3;
	}
	.front{
		
		z-index: 1;
		/* width: 300px; */
		position: absolute;
		/* top、left是以左上角为原点,因此平移以后不处于中心位置
			translate(-50%, -50%)的作用是,往上(x轴),左(y轴)移动自身长宽的50%,因此就可以居于中心位置了
		 */
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		width: 400px;
		height: 300px;
		/* background-color:lightgrey; */
		/* opacity: 0.8;	 */
		background: rgba(34,34,34,0.1);
	}
	.front .tu{
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
	}
	
	.get-code{
		display: flex;
	}
	.r{
		margin-left: 100px;
	}
	
	
	
</style>

2.userregister.vue

<template>
	<div class="app">
		<!-- 存放背景图片 -->
		<div class="background">
			<!-- img中的宽高设置图像尺寸,宽高100%是为了让整个图像显示在页面 -->
			<img :src="imgSrc" width="100%" height="100%" />
		</div>
		<!-- 存放登录表单 -->
		<div class="front1">
			<!-- <p class="img1"><img :src="imgSrc1" width="100%" height="100%" /></p> -->
			<p>用户名:<el-input type="text" style="width: 250px;" placeholder="用户名" v-model="userName" prefix-icon="el-icon-user"></el-input></p>
			<!-- 通过placeholder将文字显示出来 -->
		
				<p>手机号:<el-input type="tel"  style="width: 250px;"  placeholder="手机号"  v-model="tel" prefix-icon="el-icon-phone" /></p>
				<p>密  码:<el-input type="text" placeholder="密码"   style="width: 250px;" prefix-icon="el-icon-star-off" v-model="password"></el-input></p>
				<p>			
					<div class="get-code" @click="refreshCode()">
						验证码:	
						<el-input type="text"  style="width: 125px;" placeholder="图形验证码"  v-model="ma" prefix-icon="el-icon-picture-outline"/>
					    <s-identify class="get-code1" :identifyCode="identifyCode"></s-identify>
					</div>
				</p>
				<p class="r1">
					<el-button type="primary" plain>注册</el-button>
				</p>
			
		</div>
		
	</div>
	
	
</template>

<script>
	// 导入生成图形码的文件
	import SIdentify from "../../components/sIdentify.vue"
	export default{
		
		components:{
			SIdentify,		
		},
		data(){
			return{
				// imgSrc1:require('../../assets/img/3.png'),
				imgSrc:require('../../assets/img/2.jpg'),
				userName:'',
				tel:'',
				ma:'',
				password:'',
				identifyCode: "",
				identifyCodes: "0123456789abcdwerwshdjeJKDHRJHKOOPLMKQ",
			}
		},
		 methods: {            
		           refreshCode() {//
		             this.identifyCode = "";
		             this.makeCode(this.identifyCodes,4);
		           },
		           randomNum (min, max) {
		             max = max + 1
		             return Math.floor(Math.random() * (max - min) + min)
		           },
		           // 随机生成验证码字符串
		           makeCode (data, len) {
		             for (let i = 0; i < len; i++) {
		             this.identifyCode += data[this.randomNum(0, data.length - 1)]
		           }
		        }
				
		    }
		
	}
</script>

<style>
	
	.background{
		
		/* 宽高100%是为了铺满屏幕 */
		width: 100%;
		height: 100%;
		/* z-index用来确定层叠关系,值大的显示在值小的上面 */
		z-index: -1;
		position: absolute;
		/* 调节背景图片透明度 */
		opacity: 0.3;
	}
	.front1{
		
		z-index: 1;
		/* width: 300px; */
		position: absolute;
		/* top、left是以左上角为原点,因此平移以后不处于中心位置
			translate(-50%, -50%)的作用是,往上(x轴),左(y轴)移动自身长宽的50%,因此就可以居于中心位置了
		 */
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		/* width: 400px;
		height: 300px; */
		/* background-color:lightgrey; */
		/* opacity: 0.8;	 */
		/* background: rgba(34,34,34,0.1); */
	}
	
	/* .front1 .tu1{
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
	} */
	
	.get-code{
		line-height: 50px;
		display: flex;
	}
	
	/* .img1{
		width: 400px;
		height: 50px;
	} */
	
	.r1{
		text-align: center;
	}
	
	
	
	
</style>

3.compunents下的sIdentify(用于实现验证码的)

<template>
  <div class="s-canvas">
    <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
  </div>
</template>
<script>
export default {
  name: "SIdentify",
  props: {
    identifyCode: {
      type: String,
      default: "1234"
    },
    fontSizeMin: {
      type: Number,
      default: 35
    },
    fontSizeMax: {
      type: Number,
      default: 35
    },
    backgroundColorMin: {
      type: Number,
      default: 180
    },
    backgroundColorMax: {
      type: Number,
      default: 240
    },
    colorMin: {
      type: Number,
      default: 50
    },
    colorMax: {
      type: Number,
      default: 160
    },
    lineColorMin: {
      type: Number,
      default: 100
    },
    lineColorMax: {
      type: Number,
      default: 200
    },
    dotColorMin: {
      type: Number,
      default: 0
    },
    dotColorMax: {
      type: Number,
      default: 255
    },
    contentWidth: {
      type: Number,
      default: 120
    },
    contentHeight: {
      type: Number,
      default: 40
    }
  },
  methods: {
    // 生成一个随机数
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },
    // 生成一个随机的颜色
    randomColor(min, max) {
      let r = this.randomNum(min, max);
      let g = this.randomNum(min, max);
      let b = this.randomNum(min, max);
      return "rgb(" + r + "," + g + "," + b + ")";
    },
    transparent() {
      return "rgb(255,255,255)";
    },
    drawPic() {
      let canvas = document.getElementById("s-canvas");
      let ctx = canvas.getContext("2d");
      ctx.textBaseline = "bottom";
      // 绘制背景
      // ctx.fillStyle = this.randomColor(
      //   this.backgroundColorMin,
      //   this.backgroundColorMax
      // );
      ctx.fillStyle = this.transparent();
      ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
      // 绘制文字
      for (let i = 0; i < this.identifyCode.length; i++) {
        this.drawText(ctx, this.identifyCode[i], i);
      }
      // this.drawLine(ctx)
      // this.drawDot(ctx)
    },
    drawText(ctx, txt, i) {
      ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax);
      ctx.font =
        this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei";
      let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
      let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
      var deg = this.randomNum(-10, 10);
      // 修改坐标原点和旋转角度
      ctx.translate(x, y);
      ctx.rotate((deg * Math.PI) / 180);
      ctx.fillText(txt, 0, 0);
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180);
      ctx.translate(-x, -y);
    },
    drawLine(ctx) {
      // 绘制干扰线
      for (let i = 0; i < 8; i++) {
        ctx.strokeStyle = this.randomColor(
          this.lineColorMin,
          this.lineColorMax
        );
        ctx.beginPath();
        ctx.moveTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.lineTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.stroke();
      }
    },
    drawDot(ctx) {
      // 绘制干扰点
      for (let i = 0; i < 100; i++) {
        ctx.fillStyle = this.randomColor(0, 255);
        ctx.beginPath();
        ctx.arc(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight),
          1,
          0,
          2 * Math.PI
        );
        ctx.fill();
      }
    }
  },
  watch: {
    identifyCode() {
      this.drawPic();
    }
  },
  mounted() {
    this.drawPic();
  }
};
</script>
<style>
	#s-canvas{
		border: 1px solid greenyellow;
		border-radius: 25px 25px;
		margin-top: 4px;
	}
</style>

4.router下的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import us from '../views/user/userlogin.vue'
import re from '../views/user/userregister.vue'
Vue.use(VueRouter)

const routes = [
  
 
  {
	  // 当不写路径时,重定向到登录界面
	  path:'/',
	  redirect:'/us'
  },
  {
    path: '/us',
    name: 'us',
    component: us
	// children:[
		
	// ]
  },
  {
    path: '/re',
    name: 're',
    component: re
  }
  
]

const router = new VueRouter({
  routes,
 
   mode:'history'
})

export default router

5.App.vue

<template>
  <div id="app">
	  <!-- <us></us> -->
	  <router-link to="/us"></router-link>
	  <router-view></router-view>
	  <!-- <re></re> -->
  </div>
</template>


<script>
	// 导入导航条样式
	// import us from "./views/user/userlogin.vue"
	// import re from './views/user/userregister.vue'
	export default{
		name:'App'
		// components:{
		// 	us	,
		// 	re
		// }
		
		
	}
</script>

<style>

</style>
Logo

前往低代码交流专区

更多推荐