uniapp虚拟键盘

 html部分

<div class="keyboard">
        <!-- 输入框显示区 -->
        <div class="input">
            <div @click.stop="show" v-for="(item, index) in length" :key="index"
                :class="['box-item', isFocus && currentInput === index ? 'active' : '', text[index] ? 'hight-light' : '']">
                <span>{{ text[index] }}</span>
            </div>
        </div>
        <!-- 点击键盘以外的区域隐藏键盘 -->
        <div @click.stop="hide" v-if="showKeyboard" class="bg"></div>
        <!-- 键盘区 -->
        <div ref="cusBoard" v-if="showKeyboard" class="cus-board">
            <div v-for="(line, index) in keys" :key="'line' + index" class="letter-line">
                <!-- 收起键盘 -->
                <div v-if="index === keys.length - 1" @click.stop="hide" class="action">
                    <img src="../../../static/keyborad.png" />
                </div>
                <div @click="touchStart" v-for="key in line" :key="key" :data-text="key" class="item">{{ key }}</div>
                <!-- 删除 -->
                <div v-if="index === keys.length - 1" @click.stop="handleDel" class="action">
                    <img src="../../../static/delete.png" />
                </div>
            </div>
        </div>
    </div>

js部分

export default {
    name: "Keyboard",
    props: {
        // 文本数据源
        text: {
            type: String,
            default: "",
        },
        // 固定开头
        defaultVal: {
            type: String,
            default: "",
        },
        // 输入框数量
        length: {
            type: Number,
            default: 6,
        },
    },
    data() {
        return {
            keys: [
                ["A", "B", "C", "D", "E",],
                [1, 2, 3, 4, 5,],
                [6, 7, 8, 9, 0]
            ],
            showKeyboard: false, // 控制键盘显隐
            isFocus: false, // 是否聚焦
        };
    },
    computed: {
        /**
         * 获取当前输入框下标
         * @param {void}
         * @return {void}
         */
        currentInput: function () {
            // 返回当前文本的长度
            const length = this.text.length || 0;
            return length;
        },
    },
    mounted() {
        // 更新固定开头值到文本数据源上
        this.$emit("update:text", this.defaultVal);
    },
    methods: {
        /**
         * 显示键盘
         * @param {void}
         * @return {void}
         */
        show() {
            this.isFocus = true;
            this.showKeyboard = true;
            // 需定时器执行 否则会找不到dom
            setTimeout(() => {
                // 升起键盘
                this.$refs.cusBoard.style.transform = `translateY(0)`;
            }, 20);
        },
        /**
         * 隐藏键盘
         * @param {void}
         * @return {void}
         */
        hide() {
            // 失去焦点
            this.isFocus = false;
            // 降下键盘
            this.$refs.cusBoard.style.transform = `translateY(100%)`;
            // 需定时器执行 否则会没有动画过度
            setTimeout(() => {
                this.showKeyboard = false;
            }, 500);
        },
        /**
         * 按下
         * @param {object} el 点击事件
         * @return {void}
         */
        touchStart(el) {
            // 点击目标
            let text = this.text;
            // 文本达到上限 不做处理 返回
            if (text.length >= this.length) return;
            // 拼接点击的 值
            const content = el.currentTarget.dataset.text

            text += content;
            // 更新文本数据源
            this.$emit("update:text", text);

        },

        /**
         * 点击删除键
         * @param {void}
         * @return {void}
         */
        handleDel() {
            if (this.defaultVal && this.text.length === this.defaultVal.length && this.text.indexOf(this.defaultVal) === 0) {
                // 有默认开头 如果文本只有固定开头 没有任何输入 点击删除不做任何操作
                return;
            }
            // 从后面开始 删除一个文本
            let text = this.text;
            text = text.slice(0, text.length - 1);
            this.$emit("update:text", text);
        },
    },
};

css部分

.keyboard {
    user-select: none;
}

.bg {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1;
    background: rgba(0, 0, 0, 0.5);
}

.input {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 0 auto;
}

.box-item {
    flex-basis: 35px;
    height: 40px;
    border: 1px solid #bfbfbf;
    border-radius: 2px;
    display: flex;
    align-items: center;
    justify-content: center;

    &.active {
        position: relative;
        border-color: #348fec;

        &::after {
            position: absolute;
            content: "";
            width: 1px;
            height: 50%;
            background-color: #333333;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            animation: inputFocusLine 1s infinite;
        }
    }

    &.hight-light {
        border-color: #348fec;
    }
}

@keyframes inputFocusLine {
    0% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

.cus-board {
    font-size: 15px;
    width: 375px;
    background: rgb(246, 247, 246);
    padding: 15px 5px 30px 5px;
    position: fixed;
    z-index: 9999;
    bottom: 0;
    left: 0;
    right: 0;
    transform: translateY(100%);
    transition: all 0.5s;

    .active {
        &::after {
            position: absolute;
            top: -40px;
            left: 0;
            width: 32px;
            height: 40px;
            background-color: #ffffff;
            content: attr(data-text);
            animation: itemActive 0.5s infinite;
        }
    }
}

.item,
.action {
    width: 32px;
    height: 40px;
    border-radius: 5px;
    background-color: white;
    line-height: 40px;
    text-align: center;
    position: relative;

    img {
        display: inline-block;
        width: 16px;
        height: 16px;
    }
}

@keyframes itemActive {
    0% {
        transform: scale(1);
    }

    50% {
        transform: scale(2);
    }

    100% {
        transform: scale(1);
    }
}

.line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 15px;
}

.letter-line {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    .item,
    .action {
        margin: 3px;
    }
}

可以自定义键盘以及固定开头是英文、数字...等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值