html
<view class="custom-keyboard {{show?'show':'hide'}}">
<!-- 工具栏 -->
<view class="toolbar">
<text class="complete" bindtap="hide">完成</text>
</view>
<!-- 键盘 -->
<view class="keyboard">
<view class="row" wx:for="{{keyboard}}" wx:for-item="rows" wx:for-index="rowIndex" wx:key="rowIndex">
<block wx:for="{{rows}}" wx:for-item="col" wx:key="col">
<text wx:if="{{col.disabled}}" class="col disabled">{{col.value}}</text>
<text wx:elif="{{col.empty}}" class="col empty">{{col.value}}</text>
<view wx:elif="{{col.backspace}}" class="col backspace" bindtap="delete">
<!-- <image class="icon" src="/images/backspace.png"></image> -->
</view>
<text wx:else class="col" bindtap="click" data-value="{{col}}">{{col}}</text>
</block>
</view>
</view>
<!-- 底部,高度适配safeArea -->
<view class="footer"></view>
</view>
js
Component({
properties: {
/**
* 键盘类型
* 1:省份简称
* 2:蓝牌普通车牌:车牌号数字+字母
* 3:新能源车牌
*/
keyboardType: {
type: Number,
value: 1
},
},
data: {
keyboard: [],
show: false,
provinces: [
['京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑'],
['湘', '皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂'],
['甘', '晋', '蒙', '陕', '吉', '闽', '贵', '粤', '青'],
['藏', '川', '宁', '琼', '使', '无', {
value: '',
empty: true
}, {
value: '',
empty: true
}, {
value: '',
backspace: true
}],
],
nomals: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', {
value: 'O',
disabled: true
}, 'P', '港'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '澳'],
['Z', 'X', 'C', 'V', 'B', 'N', 'M', '学', '领', {
value: '',
backspace: true
}],
],
ecos: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', {
value: 'O',
disabled: true
}, 'P', {
value: '港',
disabled: true
}],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', {
value: '澳',
disabled: true
}],
['Z', 'X', 'C', 'V', 'B', 'N', 'M', {
value: '学',
disabled: true
}, {
value: '领',
disabled: true
}, {
value: '',
backspace: true
}],
]
},
lifetimes: {
created() {},
attached() {
this.change(this.properties.keyboardType);
},
detached() {}
},
methods: {
change(keyboardType) {
switch (parseInt(keyboardType)) {
case 1:
this.setData({
keyboard: this.data.provinces
});
break;
case 2:
this.setData({
keyboard: this.data.nomals
});
break;
case 3:
this.setData({
keyboard: this.data.ecos
});
break;
}
},
show() {
if (!this.data.show) {
this.setData({
show: true
});
}
},
hide(e) {
this.setData({
show: false
});
},
delete(e) {
this.triggerEvent('delete');
},
click(e) {
this.triggerEvent('click', e.target.dataset.value);
}
}
})
css
.custom-keyboard {
display: flex;
flex-direction: column;
border-top: 1rpx solid #e6e6e6;
position: absolute;
bottom: 0;
width: 100%;
transform: translateY(100%);
transition: all .5s cubic-bezier(0, 1, 0.5, 1);
}
.custom-keyboard.show {
transform: translateY(0%);
}
.custom-keyboard.hide {
transform: translateY(100%);
}
.custom-keyboard .toolbar {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
padding: 15rpx 10rpx;
color: #05aeff;
background-color: #ffffff;
}
.custom-keyboard .keyboard {
background-color: #d1d4db;
display: flex;
flex-direction: column;
padding: 40rpx 10rpx;
}
.custom-keyboard .keyboard .row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
margin-bottom: 20rpx;
}
.custom-keyboard .keyboard .row:last-child {
margin-bottom: 0;
}
.custom-keyboard .keyboard .row .col {
width: 65rpx;
height: 84rpx;
line-height: 84rpx;
text-align: center;
background-color: #ffffff;
border-radius: 10rpx;
margin-right: 15rpx;
box-shadow: 0rpx 6rpx 5rpx #888888;
}
.custom-keyboard .keyboard .row .col:last-child {
margin-right: 0;
}
.custom-keyboard .keyboard .row .col:active {
box-shadow: 0rpx 0rpx 0rpx #888888;
}
.custom-keyboard .keyboard .row .col.disabled {
color: #c6c6c8;
}
.custom-keyboard .keyboard .row .col.empty {
background-color: transparent;
box-shadow: unset;
}
.custom-keyboard .keyboard .row .col.backspace {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.custom-keyboard .keyboard .row .col.backspace .icon {
width: 42rpx;
height: 28rpx;
}
.custom-keyboard .footer {
height: env(safe-area-inset-bottom);
background-color: #d1d4db;
}
html2
<view class="custom-car-number-input">
<view class="cell {{item.focus?'focus':''}} {{item.eco?'eco':''}}" wx:for="{{numbers}}" wx:key="index" data-index="{{index}}" bindtap="click">
<text class="value" data-index="{{index}}" bindtap="click">{{item.value}}</text>
<text class="cursor" wx:if="{{item.focus&&item.value==''}}"></text>
</view>
</view>
js2
Component({
properties: {
},
data: {
numbers: [{
value: '',
focus: true
}, {
value: '',
focus: false
}, {
value: '',
focus: false
}, {
value: '',
focus: false
}, {
value: '',
focus: false
}, {
value: '',
focus: false
}, {
value: '',
focus: false
}, {
value: '',
focus: false,
eco: true
}]
},
lifetimes: {
created() {},
attached() {},
detached() {}
},
methods: {
click(e) {
const _index = e.target.dataset.index;
const _nums = this.data.numbers;
_nums.forEach((item, index) => {
item.focus = index == _index;
});
this.setData({
numbers: _nums
});
this.triggerEvent('focus', _index);
},
/**
* {
* index: Number,
* value: String,
* remove: Boolean
* }
*/
change(data) {
const {
index,
value,
remove
} = data;
const _nums = this.data.numbers;
_nums[index].value = remove ? '' : value;
const len = _nums.length;
let nextIndex = remove ? index - 1 : index + 1;
if (remove && nextIndex < 0) {
nextIndex = len - 1;
}
if (!remove && nextIndex >= len)
nextIndex = 0;
_nums.forEach((item, idx) => {
item.focus = idx == nextIndex;
});
this.setData({
numbers: _nums
});
this.triggerEvent('focus', nextIndex);
}
}
})
css2
.custom-car-number-input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
}
.custom-car-number-input .cell {
width: 70rpx;
height: 120rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 40rpx;
background-color: #f7f7f7;
border-radius: 10rpx;
color: #333;
}
.custom-car-number-input .cell.focus {
border: 1rpx solid #0099ff;
box-shadow: 0rpx 0rpx 10rpx #0099ff;
}
.custom-car-number-input .cell .cursor {
width: 2rpx;
height: 30rpx;
background-color: #0099ff;
animation: flashing 1.2s infinite steps(1, start);
}
@keyframes flashing {
0%,
100% {
background-color: #0099ff;
}
50% {
background-color: transparent;
}
}
.custom-car-number-input .cell.eco {
background-color: rgba(54, 210, 146, .2);
}
.custom-car-number-input .cell.eco.focus {
border-color: #36d292;
box-shadow: 0rpx 0rpx 10rpx #36d292;
}
.custom-car-number-input .cell.eco .cursor {
background-color: #36d292;
animation: flashing-eco 1.2s infinite steps(1, start);
}
@keyframes flashing-eco {
0%,
100% {
background-color: #36d292;
}
50% {
background-color: transparent;
}
}