<template>
<view class="u-char-box">
<view class="u-char-flex">
<input
:disabled="disabledKeyboard"
:value="valueModel"
type="number"
:focus="focus"
:maxlength="maxlength"
class="u-input"
@input="getVal"
/>
<view v-for="(item, index) in maxlength" :key="index">
<view
:class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
charArrLength === index && mode == 'box' ? 'u-box-active' : '',
mode === 'box' ? 'u-box' : '']"
:style="{
fontWeight: bold ? 'bold' : 'normal',
fontSize: fontSize + 'rpx',
width: width + 'rpx',
height: width + 'rpx',
color: inactiveColor
}"
>
<view
class="u-placeholder-line"
:style="{
display: charArrLength === index ? 'block' : 'none',
height: width * 0.5 +'rpx'
}"
v-if="mode !== 'middleLine'"
></view>
<view
v-if="mode === 'middleLine' && charArrLength <= index"
:class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-middle-line-active' : '']"
class="u-middle-line"
:style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"
></view>
<view
v-if="mode === 'bottomLine'"
:class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-buttom-line-active' : '']"
class="u-bottom-line"
:style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"
></view>
<block v-if="!dotFill">{{ charArr[index] ? charArr[index] : ''}}</block>
<block v-else>
<text class="u-dot">{{ charArr[index] ? '●' : ''}}</text>
</block>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'u-message-input',
props: {
maxlength: {
type: [Number, String],
default: 4
},
dotFill: {
type: Boolean,
default: false
},
mode: {
type: String,
default: 'box'
},
value: {
type: [String, Number],
default: ''
},
breathe: {
type: Boolean,
default: true
},
focus: {
type: Boolean,
default: false
},
bold: {
type: Boolean,
default: false
},
fontSize: {
type: [String, Number],
default: 30
},
activeColor: {
type: String,
default: '#2979ff'
},
inactiveColor: {
type: String,
default: '#606266'
},
width: {
type: [Number, String],
default: '40'
},
disabledKeyboard: {
type: Boolean,
default: false
}
},
watch: {
maxlength: {
immediate: true,
handler(val) {
this.maxlength = Number(val)
}
},
value: {
immediate: true,
handler(val) {
val = String(val)
this.valueModel = val.substring(0, this.maxlength)
}
}
},
data() {
return {
valueModel: ''
}
},
computed: {
animationClass() {
return index => {
if (this.breathe && this.charArr.length == index) return 'u-breathe'
else return ''
}
},
charArr() {
return this.valueModel.split('')
},
charArrLength() {
return this.charArr.length
}
},
methods: {
getVal(e) {
let { value } = e.detail
this.valueModel = value
if (String(value).length > this.maxlength) return
this.$emit('change', value)
if (String(value).length == this.maxlength) {
this.$emit('finish', value)
}
}
}
}
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
@keyframes breathe {
0% {
opacity: 0.3;
}
50% {
opacity: 1;
}
100% {
opacity: 0.3;
}
}
.u-char-box {
text-align: center;
}
.u-char-flex {
display: flex;
justify-content: center;
flex-wrap: wrap;
position: relative;
}
.u-input {
position: absolute;
top: 0;
left: -100%;
width: 200%;
height: 100%;
text-align: left;
z-index: 9;
opacity: 0;
background: none;
}
.u-char-item {
position: relative;
width: 45rpx;
height: 45rpx;
margin: 10rpx 10rpx;
font-size: 30rpx;
font-weight: bold;
color: $u-main-color;
line-height: 45rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-middle-line {
border: none;
}
.u-box {
box-sizing: border-box;
border: 2rpx solid #cccccc;
border-radius: 6rpx;
}
.u-box-active {
overflow: hidden;
animation-timing-function: ease-in-out;
animation-duration: 1500ms;
animation-iteration-count: infinite;
animation-direction: alternate;
border: 2rpx solid $u-type-primary;
}
.u-middle-line-active {
background: $u-type-primary;
}
.u-breathe {
animation: breathe 2s infinite ease;
}
.u-placeholder-line {
display: none;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2rpx;
height: 20rpx;
background: #333333;
animation: twinkling 1.5s infinite ease;
}
.u-animation-breathe {
animation-name: breathe;
}
.u-dot {
font-size: 17rpx;
line-height: 17rpx;
}
.u-middle-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.u-buttom-line-active {
background: $u-type-primary;
}
.u-bottom-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
bottom: 0;
left: 50%;
transform: translate(-50%);
}
</style>