微信小程序实现输入车牌号功能_微信小程序车牌插件
微信小程序车牌号输入组件的实现与解析
在车辆相关应用开发中,车牌号输入是一个常见需求。由于车牌号格式特殊(包含地区简称、字母和数字组合),普通输入框难以满足需求。本文将介绍如何在微信小程序中实现一个功能完善的车牌号输入组件,包含地区选择、字母数字输入、特殊格式处理等功能。先看一张示例图片:
一、组件功能概述
该车牌号输入组件具有以下核心功能:
- 支持中国各省市地区简称的选择(含特殊车牌类型)
- 字母与数字输入区域的切换
- 符合车牌号规则的输入逻辑控制(如某些字母不可用)
- 带动画效果的交互反馈
- 完整车牌号的生成与验证
二、核心功能实现细节
车牌号格式处理
车牌号格式为 “地区简称 + 字母 +・+5 位字母数字组合”,组件在第 3 个位置固定显示 “・” 分隔符,其他位置根据输入逻辑填充。
输入位置控制
实现了特殊的输入位置移动逻辑,当在第 1 个位置输入后自动跳转到第 3 个位置,跳过分隔符位置,符合车牌号输入习惯。
非法输入限制
对容易与数字混淆的字母 (I、O) 进行了限制,防止用户输入导致的识别错误。
动画交互效果
- 脉冲动画:用于突出显示可点击区域
- 渐变动画:为字母数字按键添加动态效果
- 选中状态:通过边框颜色变化提供反馈
三、贴入完整的实现源码:
1、js代码:
Page({ /** * 页面的初始数据 */ data: { current: 0, inputIndex: 0, keyAttr: [], areaList: [{ \"id\": \"1300\", \"value\": \"冀\" }, { \"id\": \"1400\", \"value\": \"晋\" }, { \"id\": \"2100\", \"value\": \"辽\" }, { \"id\": \"2200\", \"value\": \"吉\" }, { \"id\": \"2300\", \"value\": \"黑\" }, { \"id\": \"3200\", \"value\": \"苏\" }, { \"id\": \"3300\", \"value\": \"浙\" }, { \"id\": \"3400\", \"value\": \"皖\" }, { \"id\": \"3500\", \"value\": \"闽\" }, { \"id\": \"3600\", \"value\": \"赣\" }, { \"id\": \"3700\", \"value\": \"鲁\" }, { \"id\": \"4100\", \"value\": \"豫\" }, { \"id\": \"4200\", \"value\": \"鄂\" }, { \"id\": \"4300\", \"value\": \"湘\" }, { \"id\": \"4400\", \"value\": \"粤\" }, { \"id\": \"4600\", \"value\": \"琼\" }, { \"id\": \"5100\", \"value\": \"川\" }, { \"id\": \"5200\", \"value\": \"贵\" }, { \"id\": \"5300\", \"value\": \"云\" }, { \"id\": \"6100\", \"value\": \"陕\" }, { \"id\": \"6200\", \"value\": \"甘\" }, { \"id\": \"6300\", \"value\": \"青\" }, { \"id\": \"7100\", \"value\": \"台\" }, { \"id\": \"1500\", \"value\": \"蒙\" }, { \"id\": \"4500\", \"value\": \"桂\" }, { \"id\": \"5400\", \"value\": \"藏\" }, { \"id\": \"6400\", \"value\": \"宁\" }, { \"id\": \"6500\", \"value\": \"新\" }, { \"id\": \"1100\", \"value\": \"京\" }, { \"id\": \"1200\", \"value\": \"津\" }, { \"id\": \"3100\", \"value\": \"沪\" }, { \"id\": \"5000\", \"value\": \"渝\" }, { \"id\": \"8100\", \"value\": \"港\" }, { \"id\": \"8200\", \"value\": \"澳\" }, { \"id\": \"9001\", \"value\": \"使\" }, { \"id\": \"9002\", \"value\": \"领\" }, { \"id\": \"9003\", \"value\": \"警\" }, { \"id\": \"9004\", \"value\": \"学\" }, { \"id\": \"9\", \"value\": \"ABC/123\" } ], letterList: [ [{ \"id\": \"001\", \"value\": \"1\" }, { \"id\": \"002\", \"value\": \"2\" }, { \"id\": \"003\", \"value\": \"3\" }, { \"id\": \"004\", \"value\": \"4\" }, { \"id\": \"005\", \"value\": \"5\" }, { \"id\": \"006\", \"value\": \"6\" }, { \"id\": \"007\", \"value\": \"7\" }, { \"id\": \"008\", \"value\": \"8\" }, { \"id\": \"009\", \"value\": \"9\" }, { \"id\": \"010\", \"value\": \"0\" } ], [{ \"id\": \"9010\", \"value\": \"Q\" }, { \"id\": \"9011\", \"value\": \"W\" }, { \"id\": \"9012\", \"value\": \"E\" }, { \"id\": \"9013\", \"value\": \"R\" }, { \"id\": \"9014\", \"value\": \"T\" }, { \"id\": \"9015\", \"value\": \"Y\" }, { \"id\": \"9016\", \"value\": \"U\" }, { \"id\": \"9017\", \"value\": \"I\" }, { \"id\": \"9018\", \"value\": \"O\" }, { \"id\": \"9019\", \"value\": \"P\" } ], [{ \"id\": \"9020\", \"value\": \"A\" }, { \"id\": \"9021\", \"value\": \"S\" }, { \"id\": \"9022\", \"value\": \"D\" }, { \"id\": \"9023\", \"value\": \"F\" }, { \"id\": \"9024\", \"value\": \"G\" }, { \"id\": \"9025\", \"value\": \"H\" }, { \"id\": \"9026\", \"value\": \"J\" }, { \"id\": \"9027\", \"value\": \"K\" }, { \"id\": \"9028\", \"value\": \"L\" } ], [{ \"id\": \"9030\", \"value\": \"Z\" }, { \"id\": \"9031\", \"value\": \"X\" }, { \"id\": \"9032\", \"value\": \"C\" }, { \"id\": \"9033\", \"value\": \"V\" }, { \"id\": \"9034\", \"value\": \"B\" }, { \"id\": \"9035\", \"value\": \"N\" }, { \"id\": \"9036\", \"value\": \"M\" }, { \"id\": \"0\", \"value\": \"DEL\" } ] ] }, // 输入框点击事件 codeClick(e) { const val = e.currentTarget.dataset.tag; // 当点击的不是第三个输入框时更新当前输入状态 if (val !== 2 && val !== 8) { this.setData({ current: val === 0 ? 0 : 1, inputIndex: val }); } if(val == 8){ let plate = this.data.keyAttr; this.generatePlateNumber(plate); } }, generatePlateNumber: function(array) { // 校验数组长度 if (array.length !== 8) { wx.showToast({ title: \'请选择8个元素\', icon: \'none\' }) return; } let plateNumber = \"\"; // 遍历数组生成车牌号 for (let i = 0; i < array.length; i++) { if (i ===2) { plateNumber += \"·\"; } else { plateNumber += array[i]; } } wx.showModal({ title: \'提示\', content: \'你所输入的编号是\\n【\'+plateNumber+\'】\', showCancel: false, confirmText: \'知道了\' }) }, // 按键点击事件 keyClick(e) { const { item } = e.currentTarget.dataset; const { inputIndex } = this.data; // 处理特殊按键 if (item.id === \'0\') { // 删除键 this.handleDeleteKey(); return; } if (item.id === \'9\') { // 字母数字切换键 this.setData({ current: 1, inputIndex: 1 }); return; } // 处理不可选择的按键 if ([\'9017\', \'9018\'].includes(item.id)) { wx.showToast({ title: \'不合法选项\', icon: \'none\' }); return; } // 处理正常输入 this.setData({ [`keyAttr[${inputIndex}]`]: item.value }, () => { // 更新到下一个输入位置 this.moveToNextInput(); }); }, // 处理删除键逻辑 handleDeleteKey() { const { inputIndex } = this.data; let val = inputIndex - 1; // 特殊位置处理 if (inputIndex === 3) val = 1; if (inputIndex === 0) val = 7; // 清除当前位置的值并移动焦点 this.setData({ [`keyAttr[${inputIndex}]`]: \'\', current: val === 0 ? 0 : 1, inputIndex: val }); }, // 移动到下一个输入位置 moveToNextInput() { const { inputIndex } = this.data; let val = inputIndex + 1; // 特殊位置处理 if (inputIndex === 1) val = 3; if (inputIndex === 7) val = 0; // 更新当前输入状态 this.setData({ current: val === 0 ? 0 : 1, inputIndex: val }); }, /** * 用户点击右上角分享 */ onShareAppMessage() { }})
2、wxml代码:
<view class=\"car input\"> <block wx:for=\"{{9}}\" wx:for-item=\"item\" wx:for-index=\"index\" wx:key=\"item\"> <view class=\"frame {{index==8?\'span\':\'\'}} {{inputIndex==index?\'active\':\'\'}}\" bind:tap=\"codeClick\" data-tag=\"{{index}}\"> <text wx:if=\"{{index==2}}\">·</text> <text wx:elif=\"{{index==8}}\">确 定</text> <text wx:else>{{keyAttr[index]}}</text> </view> </block></view><view class=\"key-box\"> <view class=\"car area\" wx:if=\"{{current==0}}\"> <block wx:for=\"{{areaList}}\" wx:for-item=\"item\" wx:for-index=\"index\" wx:key=\"item\"> <view class=\"plate {{item.id==9?\'span\':\'border\'}}\" bind:tap=\"keyClick\" data-item=\"{{item}}\">{{item.value}}</view> </block> </view> <block wx:for=\"{{4}}\" wx:for-item=\"big\" wx:for-index=\"index\" wx:key=\"big\" wx:if=\"{{current==1}}\"> <view class=\"car letter-{{inputIndex<2?(index+1):index}}\"> <block wx:for=\"{{letterList[inputIndex<2?(index+1):index]}}\" wx:for-item=\"item\" wx:for-index=\"small\" wx:key=\"item\"> <view bind:tap=\"keyClick\" data-item=\"{{item}}\"> <view class=\"plate disable\" wx:if=\"{{item.id==9017 || item.id==9018}}\"> {{item.value}} </view> <view class=\"plate delete\" wx:elif=\"{{item.id==0}}\"> {{item.value}} </view> <view class=\"plate change color-{{index}}\" wx:else>{{item.value}}</view> </view> </block> </view> </block></view>
3、wxss代码:
page { background-color: white;}.key-box { position: fixed; bottom: 0; left: 0; right: 0; padding: 20rpx 0; background-color: #f1f1f1;}.car { display: grid; grid-gap: 10rpx; font-size: 30rpx; margin: 10rpx;}.input { padding: 20rpx 0; grid-template-columns: repeat(10, 1fr);}.frame { background-color: white; padding: 15rpx; text-align: center; border-radius: 10rpx; border: 1rpx dashed rgb(109, 108, 108);}.active { border: 1rpx solid rgb(231, 8, 8);}.area { grid-template-columns: repeat(8, 1fr);}.letter-0,.letter-1 { grid-template-columns: repeat(10, 1fr);}.letter-2 { grid-template-columns: repeat(9, 1fr);}.letter-3 { grid-template-columns: repeat(8, 1fr);}.plate { background-color: white; padding: 15rpx 10rpx; text-align: center; border-radius: 10rpx; box-shadow: 1rpx 1rpx 0 1rpx #7c7c7c;}.disable { color: #9a9a9b; background-color: rgb(190, 190, 190);}.border { animation: pulse 3s infinite;}/* 脉冲发光动画 */@keyframes pulse { 0% { box-shadow: 6rpx 1rpx 0 3rpx rgba(244, 161, 66, 0.8); } 50% { box-shadow: 3rpx 3rpx 0 1rpx rgba(53, 235, 7, 0.5); } 100% { box-shadow: 3rpx 2rpx 0 3rpx rgba(243, 8, 8, 0.8); }}.change { color: transparent; background-clip: text; -webkit-background-clip: text; animation: gradientMove 1s linear infinite; background-size: 200% 100%;}.color-0 { color: #fc5a04;}.color-1 { background-image: linear-gradient(to right, #02dbf8, #f706a6);}.color-2 { background-image: linear-gradient(to left, #f88d02, #3514f0);}.color-3 { background-image: linear-gradient(to right, #e402f8, #1a206e);}@keyframes gradientMove { 0% { background-position: 0% 0; } 100% { background-position: 200% 0; }}.delete { color: white; letter-spacing: 4rpx; background-color: #F43F5E; background-image: none;}.span { color: white; grid-column: span 2; background-color: #007FFF;}
4、json代码:
{ \"usingComponents\": {}, \"navigationBarTitleText\": \"车牌号示例\", \"navigationBarTextStyle\": \"black\", \"navigationBarBackgroundColor\": \"#FFFFFF\"}
四、优化与拓展方向
1. 支持更多车牌类型
目前组件支持普通车牌和部分特殊车牌,可扩展支持新能源车牌、教练车牌等更多类型。
2. 增加输入校验
可添加实时校验功能,在输入过程中提示格式错误,提升用户体验。
3. 支持扫描识别
集成 OCR 功能,支持通过摄像头扫描识别车牌号,减少手动输入。
4. 适配不同平台
可进一步优化样式,使其在不同尺寸的屏幕上有更好的显示效果。
布局简单,对于初学者可以用来看看,随便写的,如果出现运行异常,请使用真机预览呦~
五、总结
这个微信小程序车牌号输入组件实现了完整的车牌号输入功能,包含地区选择、字母数字输入、特殊格式处理和动画交互效果。通过合理的逻辑设计和样式实现,既满足了功能需求,又提供了良好的用户体验。
在实际项目中,可根据具体需求对组件进行扩展和优化,使其更好地适配业务场景。该组件的实现思路也可应用于其他需要特殊格式输入的场景,如手机号、身份证号等输入组件的开发。
更多示例,请关注 蒜鸟编程(微信小程序 / 抖音 / 小红书/微信公众号/微博****等同名称),在这里,编程与生活的边界从未如此清晰,期待与大家共同成长!后续将围绕编程技术持续更新更多实践示例,如果在实现过程中遇到问题,或者有更好的优化建议,欢迎在评论区交流讨论!