这样的一个样式很简单, 整体思路是首先在布局中要有一个真实的输入框, 通过透明度隐藏掉。然后覆盖层上开始写自定义样式, 通过动画布局模拟出你想要的输入框样式。
下图为美团App等短信验证码布局
接下来使用 vue3 + typescript 实现该功能
<!-- 模版布局 -->
<template>
<div class="input-diy">
<p>美团App验证码输入框DEMO</p>
<div class="input-wrap">
<input
maxlength="4"
type="number"
v-model="currentPwd"
/>
<span
v-for="(val, index) in pwdList"
:key="index"
:class="customClass(index)">
{{ pwdArr[index] }}
</span>
</div>
</div>
</template>
// 逻辑代码
<script lang="ts">
import {
ref,
watch,
reactive,
defineComponent,
} from 'vue';
export default defineComponent({
setup() {
let currentPwd=ref<string>(''), // 输入的验证码值
pwdArr=reactive<string[]>([]), // 输入框内的值
pwdLength=ref<number | null>(0), // 已经输入的验证码长度,默认为0,显示光标
pwdList=reactive<boolean[]>([false, false, false, false]); // 初始化验证码数据
watch(()=>{
return currentPwd.value;
}, (val)=>{
watchCurrentPwd(val);
})
/**
* 监听input验证码改变
*/
const watchCurrentPwd=(newVal: String)=> {
let nval=newVal.toString().replace(/\s+/g,"");
pwdLength.value=nval.length || 0;
pwdList.forEach((val: boolean, i: number)=> {
pwdArr[i]=nval.slice(i, i + 1); // 获取输入inputvalue放入验证码框
});
if(nval.length > 4) { // 截取四位数据
currentPwd.value=nval.slice(0, 4);
} else if( nval.length===4 ) {
pwdLength.value=null; // 输完验证码 取消光标
}
}
/**
* 自定义类名
*/
const customClass=(index: Number)=> {
return index===pwdLength.value ? 'active' : '';
}
return {
pwdArr,
pwdList,
pwdLength,
currentPwd,
customClass
}
}
});
</script>
/* CSS 样式 */
<style scope>
.input-wrap {
position: relative;
display: flex;
justify-content: center;
margin-top: 25px;
overflow: hidden;
}
/* 真实输入框 */
.input-wrap input {
opacity: 0;
color: transparent;
position: absolute;
top: 0;
left: -50%;
/*bottom: 0;*/
width: 750px;
height: 150%;
z-index: 2;
text-align: left;
}
/* 模拟验证码输入框 */
.input-wrap span {
width: 60px;
height: 60px;
border-bottom: 2px solid #BDC2CC;
margin-right: 25px;
position: relative;
top: 0;
left: 0;
text-align: center;
line-height: 60px;
font-size: 28px;
color: #303747;
}
.input-wrap span:last-child {
margin-right: 0;
}
/*模拟光标底部*/
.input-wrap .active {
border-bottom: 2px solid #22242A;
}
/*模拟光标闪烁*/
.input-wrap .active:after {
content: '';
position: absolute;
bottom: -2px;
left: 30px;
display: block;
width: 2px;
height: 30px;
background-color: #22242A;
transform: translate(-50%, -50%);
animation: focus 1s infinite;
}
.input-wrap-diy{
position: relative;
}
/* 光标动画 */
@keyframes focus {
0% {
opacity: 1
}
50% {
opacity: 1
}
51% {
opacity: 0
}
99% {
opacity: 0
}
}
</style>
你学废了么? 如果想了解更多的web小程序开发知识, 请点赞收藏加关注啊。手撸不易!持续更新...
DEMO效果图
<script src="https://lf3-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
1.按钮点击之后,会把按钮禁用
2.同时按钮里面 的内容也会变化,注意button里面的内容通过innerHTML修改
3.里面的秒数是有变化的,因此需要一个定时器
4.定义一个变量,在定时器里面,不断递减
5.如果变量为0说明到时间了,我们需要停止定时器,并且复原按钮的初始状态
天在小破站看到一个前端生成随机验证码的视频,感觉很有意思,就跟着操作了一下,成功了。
后来自己又想给它加一个提交按钮,输入并判断验证码的正确性,也可以正常运行,但是我的代码好像还是存在一些bug:
1.canvas标签是绘图容器,自带属性使它是一个默认300*150的容器,缩小canvs容器时,里面的绘图也会变小,我没有找到合适的方法去调整它的大小。
2.对于输入框input,我使用了float浮动,为了使input输入框和canvas里面的验证码并排,但是被vscode警告了。
这次的实战练习也经历了很多坎坷,但是也收获很大。学习到了canvas标签的用法、JS全局变量和局部变量、以及有关context的一些属性和方法。
最后,希望路过的大佬,帮我看看bug,帮帮菜鸟。
附上源码
*请认真填写需求信息,我们会在24小时内与您取得联系。