小程序--自定義鍵盤車牌號

沒啥特別的技術,就是記錄一下本身開發時遇到的問題和解決方案,之後本身查看着方便css

簡介

自定義的車牌號鍵盤html

效果json

要實現一個方便輸入車牌號的鍵盤和輸入框,支持新能源車牌。小程序

最開始的想法是用多個小程序的input輸入框實現,可是發現了一個很不爽的體驗,每一個的輸入框聚焦都會引起手機鍵盤的彈出,emmmm,這可不是我要的效果。數組

最終的實現方案就是 沒用到一個input輸入框,所有使用的div實現輸入框效果。將鍵盤選中的內容存到一個數組裏,輸入框裏展現對應數組的文字。app

我把它寫成一個component,方便多頁面使用xss

wxml文件flex

<view class="modal-box">
        <view class="modal-wrapper">
            <view class="modal-title">
                <view class="titleWrapper"><text class="title-text">請錄入車牌號</text></view>
                <view class="iconWrapper"><image class="close-icon" src="../images/close.png" bindtap="onCancel" /></view>
            </view>
            
            <view class="modal-content">
                <view class="modal-input">
                    <block wx:for="{{8}}" wx:key="index">
                        <view data-index="{{index}}" class="input {{selectInputIndex===index?'activeInput':''}}" bindtap='inputCarNum'>
                            <text>{{carNumArr[index] || ''}}</text>
                        </view>
                    </block>
                    <view class="line"></view>
                </view>
                
            </view>
            <view class="model-btn-group">
                <button bindtap="onOk" class="btn confirm" disabled="{{btnDisabled}}">確認</button>
            </view>
        </view>
        <!-- 車牌 -->
        <view class='keyboard' >
          <!-- 省鍵盤 -->
          <view class="provinces" hidden='{{hiddenPro}}'>
            <view class="pro-li fl" wx:for="{{provinceArr}}" wx:key="index" catchtap='proTap' data-province="{{item}}">{{item}}</view>
          </view>
          <!-- 號碼鍵盤 -->
          <view class="keyNums" hidden='{{hiddenStr}}'>
            <view wx:if="{{selectInputIndex===1}}" class="row numRow">
              <view class="pro-li disabled" wx:for="{{numArr}}" wx:key="index" data-str="{{item}}">{{item}}</view>
            </view>
           <view wx:else class="row numRow">
               <view class="pro-li " wx:for="{{numArr}}" wx:key="index" catchtap='strTap' data-str="{{item}}">{{item}}</view>
            </view>
           <view class="strOne row">
              <view class="pro-li " wx:for="{{strArrOne}}" wx:key="index" catchtap='strTap' data-str="{{item}}">{{item}}</view>
            </view>
           <view class="strTwo row">
              <view class="pro-li " wx:for="{{strArrTwo}}"wx:key="index" catchtap='strTap' data-str="{{item}}">{{item}}</view>
           </view>
           <view class="strThree row">
              <view class="pro-li " wx:for="{{strArrThree}}" wx:key="index" catchtap='strTap' data-str="{{item}}">{{item}}</view>
              <view class='kb-icon pro-li' catchtap='backSpace'>
                <image class='delete-icon' src="../images/delete.png" />
              </view>
           </view>
          </view>
        </view>
       <view class="modal-cover"></view>   
    </view>


複製代碼

js代碼ui

const INPUT_NUM = 8;//車牌號輸入框個數
const EmptyArray = new Array(INPUT_NUM).fill('');//['','','','','','','','']

// 車牌輸入框的下標
const INPUT_INDEX = {
  FIRST: 0,
  SECOND: 1
};

Component({
  data: {
    // 鍵
    provinceArr: ['京', '滬', '津', '蘇', '粵', '冀', '晉', '蒙', '遼', '吉', '黑', '浙', '皖', '閩', '贛', '魯', '豫', '鄂', '湘', 
      '桂', '瓊', '渝', '川', '貴', '雲', '藏', '陝', '甘', '青', '寧', '新', '港', '澳', '臺'],
    strArrOne: ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'P'],
    strArrTwo: ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
    strArrThree: ['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
    numArr: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
    hiddenPro: false, // 隱藏省份鍵盤
    hiddenStr: true, // 隱藏數字字母鍵盤
    carNumArr: EmptyArray,
    selectInputIndex: 0,
    btnDisabled: true
  },
  methods: {
    proTap(e) { //點擊省份
      let province = e.currentTarget.dataset.province;
      const { carNumArr, selectInputIndex } = this.data;
      this.setData({
        hiddenPro: true,
        hiddenStr: false
      });
      carNumArr[selectInputIndex] = province;
      // 選擇車牌號時觸發
      this.setData({
        carNumArr,
        // 選中一個後,下一個輸入框聚焦
        selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex,
        btnDisabled: this.btnDisabled()
      });
    },
    strTap(e) { //點擊字母數字
      const str = e.currentTarget.dataset.str;
      const { carNumArr, selectInputIndex } = this.data;
      carNumArr[selectInputIndex] = str;
      this.setData({
        carNumArr,
        // 選中一個後,下一個輸入框聚焦
        selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex,
        btnDisabled: this.btnDisabled()
      });
    },
    inputCarNum(e) {
      const { index } = e.currentTarget.dataset;
      this.setData({
        showCarKeyboard: true,
        selectInputIndex: index
      });
      if (index === INPUT_INDEX.FIRST) {
        // 第一個輸入框展現省份鍵盤,第二個展現字母數字輸入框(數字不可點),之後就是數字字母輸入框(均可點)
        this.setData({
          hiddenPro: false,
          hiddenStr: true
        });
      } else if (index === INPUT_INDEX.SECOND) {
        this.setData({
          hiddenPro: true,
          hiddenStr: false
        });
      } else {
        this.setData({
          hiddenPro: true,
          hiddenStr: false
        });
      }
    },
    backSpace() { //刪除
      const { carNumArr, selectInputIndex } = this.data;
      carNumArr[selectInputIndex] = '';
      this.setData({
        carNumArr,
        selectInputIndex: selectInputIndex !== INPUT_INDEX.FIRST ? selectInputIndex - 1 : selectInputIndex,
        btnDisabled: this.btnDisabled()
      }, () => {
        if (this.data.selectInputIndex === INPUT_INDEX.FIRST) { //這裏必需要用this.data.selectInputIndex,用最新的
          this.setData({
            hiddenPro: false,
            hiddenStr: true
          });
        }
      });
    },
    // 只有輸入內容的車牌號位數合法時,展現確認按鈕
    btnDisabled() {
      const { carNumArr } = this.data;
      const disabled = carNumArr.some((item, index) => {
        if (index !== carNumArr.length - 1) {
          return !item;
        }
        return false;
      });
      return disabled;
    },
    onCancel() {
      this.setData({ carNumArr: EmptyArray });
      this.triggerEvent('onCancel');
    },
    onOk() {
      const carNum = this.data.carNumArr.join('');
      this.triggerEvent('onOk', carNum);
    }
  },
});
複製代碼

wxss文件this

/* 鍵盤 */
.keyboard {
	width: 100%;
	position: fixed;
	bottom: 0;
	left:0;
	z-index: 1000;
	background-color: rgba(210, 213, 219, 90);
}

.fl {
	float: left
}

.carnum {
	text-align: center;
	height: 88rpx
}

.tel {
	border-bottom: 2rpx solid #ddd;
	height: 100rpx;
	line-height: 100rpx;
}

.provinces {
	overflow: hidden;
	padding-top: 20rpx;
}

.pro-li {
	font-size: 32rpx;
	color: #353535;
	height: 76rpx;
	width: 62rpx;
	line-height: 76rpx;
	text-align: center;
	margin-left: 12rpx;
	margin-bottom: 20rpx;
	background-color: #fff;
	box-shadow: 0px 1rpx 2rpx 0 #979797;
	border-radius: 5px;
	flex: 1
}

.keyNums .disabled {
	background-color: #F7F7F7;
	color: #CCC
}

.keyNums {
	overflow: hidden;
	padding-top: 20rpx;
	display: flex;
	flex-direction: column;
}

.keyNums .row {
	display: flex;
}

.keyNums .numRow {
	padding: 0 10rpx;
}

.keyNums .strOne {
	padding: 0 10rpx;
}

.keyNums .strOne .strOneItem {
	flex: 1
}

.keyNums .strTwo {
	padding: 0 40rpx;
}

.keyNums .strOne .strTwoItem {
	flex: 1
}

.keyNums .strThree {
	padding-left: 116rpx;
	padding-right: 10rpx;
}

.keyNums .strOne .strThreeItem {
	flex: 1
}

.keyNums .strOne .strThreeItem:nth-child(7) {
	margin-left: 100px
}

.keyNums .pro-li:nth-child(16) {
	color: red
}

.keyNums .strThree .kb-del {
	margin-left: 12rpx
}

.keyNums .strThree .kb-icon {
	flex: 1.5;
	background: #ABB3BD;
	margin-left: 40rpx;
}

/* modal樣式 */

.modal-box {
	width: 100%;
	position: absolute;
	top: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: center;
}

.modal-wrapper {
	margin: 30% 30rpx;
	height: 380rpx;
	padding: 30rpx;
	background-color: #fff;
	border-radius: 10rpx;
	z-index: 300;
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	align-content: space-between;
	justify-content: space-between;
	overflow: hidden;
	text-align: left;
}

.modal-wrapper .model-btn-group {
	display: flex;
	box-sizing: border-box;
	font-size: 32rpx;
}

.model-btn-group view {
	width: 50%;
	text-align: center;
	box-sizing: border-box;
}

.model-btn-group .btn {
	flex: 1;
	font-size: 18px
}

.model-btn-group .cancel {
	color: #999;
}

.model-btn-group .confirm {
	color: #fff;
	background-color: #ff5000;
}

.model-btn-group .confirm.active {
	opacity: 1;
}

.modal-cover {
	width: 100%;
	background-color: #242424;
	opacity: 0.5;
	z-index: 299;
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	right: 0;
	margin: auto;
	overflow: hidden;
}

.modal-input {
	display: flex;
}

.modal-input .input {
	border: 1px solid #979797;
	margin-right:6rpx;
	border-radius: 3px;
	flex: 1;
	text-align: center;
	padding: 8px;
	height: 22px;
}

.modal-input .input:nth-child(1) {
	border-right-width: 0;
	margin-right: 0;
	position: relative;
	border-bottom-right-radius: 0;
	border-top-right-radius: 0;
}

.modal-input .input:nth-child(1)::after {
	content: "";
	position: absolute;
	right: -1px;
	width: 1px;
	height: 20px;
	background-color: #979797;
	z-index: -10
}


.modal-input .input:nth-child(2) {
	position: relative;
	border-left-width: 0;
	margin-right:20rpx;
	border-bottom-left-radius: 0;
	border-top-left-radius: 0;
}

.modal-input .input:nth-child(2)::after {
	content: "";
	position: absolute;
	right:-16rpx;
	top: 45%;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background-color: #979797
}

.modal-input .input:nth-child(8) {
	border: 1px dashed #979797;
}

.modal-input .activeInput {
	border-radius: 3px !important;
	border: 1px solid #FF5000 !important
}

.modal-input .text {
	text-align: right;
	color: #c5c5c5;
	font-size: 28rpx;
}

.modal-placeholder-class {
	color: #c5c5c5;
}

.modal-title {
	display: flex;
	font-size: 20px;
	color: #333333
}

.titleWrapper {
	flex: 1;
}

.title-text {
	font-size: 18px;
	font-weight: bold;
}

.iconWrapper {
	flex: 1;
	text-align: right;
}

.close-icon {
	width: 35rpx;
	height: 35rpx;
}

.delete-icon {
	width: 55rpx;
	height: 40rpx;
	margin-top: 18rpx;
}
複製代碼

json文件,標識出來這是一個component

{
  "component": true
}
複製代碼

在頁面裏如何使用呢

要在json裏引用組件

{
  "usingComponents": {
    "carKeyboard": "/components/carKeyboard/carKeyboard"
  }
}
複製代碼
<!--index.wxml-->
<view class="container">
  <view>
    <button class="btn" bindtap="inputCarNum">輸入車牌號</button>
  </view>
<block wx:if="{{showKeyboard}}">
  <carKeyboard carNum="{{carNum}}" bind:onOk="onOk" bind:onCancel="onCancel" />
</block>
</view>



複製代碼
//index.js

Page({
  data: {
    carnum: '',
    showKeyboard:false,
  },
  inputCarNum() {
    this.setData({showKeyboard: true})
  },
 
  onOk(e){
    console.log(e.detail,'輸入的車牌號')
  },
  onCancel(){
    this.setData({ showKeyboard: false   })
  }
})
複製代碼
相關文章
相關標籤/搜索