Vue制作良好交互的信用卡表单

2022-05-11  本文已影响0人  ohityes

这是使用 Vue 制作的信用卡制卡表单,该表单的交互设计出色,除了表单之外,还有一张示例卡,在表单里输入任何信息,如卡号、持有人、到期日等,都会有动画框聚焦到示例卡的对应区域,让用户更清楚的知道当前输入的是什么信息,在银行信用卡申请页面展示是一个很好的选择。

良好交互的信用卡表单
查看效果:Vue制作良好交互的信用卡表单演示

制作过程

1、HTML

<div class="wrapper" id="dowebok">
    <div class="card-form">
        ...
        <div class="card-form__inner">
            <div class="card-input">
                <label for="cardNumber" class="card-input__label">信用卡号码</label>
                <input type="text" id="cardNumber" class="card-input__input" v-mask="generateCardNumberMask"
                    v-model="cardNumber" v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardNumber"
                    autocomplete="off">
            </div>
            <div class="card-input">
                <label for="cardName" class="card-input__label">持有者姓名</label>
                <input type="text" id="cardName" class="card-input__input" v-model="cardName"
                    v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardName" autocomplete="off">
            </div>
            <div class="card-form__row">
                <div class="card-form__col">
                    <div class="card-form__group">
                        <label for="cardMonth" class="card-input__label">到期日</label>
                        <select class="card-input__input -select" id="cardMonth" v-model="cardMonth"
                            v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardDate">
                            <option value="" disabled selected>月</option>
                            <option v-bind:value="n < 10 ? '0' + n : n" v-for="n in 12"
                                v-bind:disabled="n < minCardMonth" v-bind:key="n">
                                {{n < 10 ? '0' + n : n}}
                            </option>
                        </select>
                        <select class="card-input__input -select" id="cardYear" v-model="cardYear"
                            v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardDate">
                            <option value="" disabled selected>年</option>
                            <option v-bind:value="$index + minCardYear" v-for="(n, $index) in 12" v-bind:key="n">
                                {{$index + minCardYear}}
                            </option>
                        </select>
                    </div>
                </div>
                <div class="card-form__col -cvv">
                    <div class="card-input">
                        <label for="cardCvv" class="card-input__label">校验码</label>
                        <input type="text" class="card-input__input" id="cardCvv" v-mask="'####'" maxlength="4"
                            v-model="cardCvv" v-on:focus="flipCard(true)" v-on:blur="flipCard(false)"
                            autocomplete="off">
                    </div>
                </div>
            </div>

            <button class="card-form__button">提 交</button>
        </div>
    </div>
</div>

2、CSS

CSS 代码我们也只展示表单部分:

...
.card-form {
    max-width: 570px;
    margin: auto;
    width: 100%;
}
.card-form__inner {
    background: #fff;
    box-shadow: 0 30px 60px 0 rgba(90, 116, 148, 0.4);
    border-radius: 10px;
    padding: 35px;
    padding-top: 180px;
}
.card-form__row {
    display: flex;
    align-items: flex-start;
}
.card-form__col {
    flex: auto;
    margin-right: 35px;
}
.card-form__col:last-child {
    margin-right: 0;
}
.card-form__col.-cvv {
    max-width: 150px;
}
.card-form__group {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
}
.card-form__group .card-input__input {
    flex: 1;
    margin-right: 15px;
}
.card-form__group .card-input__input:last-child {
    margin-right: 0;
}
.card-form__button {
    width: 100%;
    height: 55px;
    background: #2364d2;
    border: none;
    border-radius: 5px;
    font-size: 22px;
    font-weight: 500;
    font-family: "Source Sans Pro", sans-serif;
    box-shadow: 3px 10px 20px 0px rgba(35, 100, 210, 0.3);
    color: #fff;
    margin-top: 20px;
    cursor: pointer;
}
...

3、Javascript

JS 代码我们展示全部代码:

new Vue({
    el: "#dowebok",
    data() {
        return {
            currentCardBackground: Math.floor(Math.random() * 25 + 1),
            cardName: "",
            cardNumber: "",
            cardMonth: "",
            cardYear: "",
            cardCvv: "",
            minCardYear: new Date().getFullYear(),
            amexCardMask: "#### ###### #####",
            otherCardMask: "#### #### #### ####",
            cardNumberTemp: "",
            isCardFlipped: false,
            focusElementStyle: null,
            isInputFocused: false
        };
    },
    mounted() {
        this.cardNumberTemp = this.otherCardMask;
        document.getElementById("cardNumber").focus();
    },
    computed: {
        getCardType() {
            let number = this.cardNumber;
            let re = new RegExp("^4");
            if (number.match(re) != null) return "visa";

            re = new RegExp("^(34|37)");
            if (number.match(re) != null) return "amex";

            re = new RegExp("^5[1-5]");
            if (number.match(re) != null) return "mastercard";

            re = new RegExp("^6011");
            if (number.match(re) != null) return "discover";

            re = new RegExp('^9792')
            if (number.match(re) != null) return 'troy'

            return "visa";
        },
        generateCardNumberMask() {
            return this.getCardType === "amex" ? this.amexCardMask : this.otherCardMask;
        },
        minCardMonth() {
            if (this.cardYear === this.minCardYear) return new Date().getMonth() + 1;
            return 1;
        }
    },
    watch: {
        cardYear() {
            if (this.cardMonth < this.minCardMonth) {
                this.cardMonth = "";
            }
        }
    },
    methods: {
        flipCard(status) {
            this.isCardFlipped = status;
        },
        focusInput(e) {
            this.isInputFocused = true;
            let targetRef = e.target.dataset.ref;
            let target = this.$refs[targetRef];
            this.focusElementStyle = {
                width: `${target.offsetWidth}px`,
                height: `${target.offsetHeight}px`,
                transform: `translateX(${target.offsetLeft}px) translateY(${target.offsetTop}px)`
            }
        },
        blurInput() {
            let vm = this;
            setTimeout(() => {
                if (!vm.isInputFocused) {
                    vm.focusElementStyle = null;
                }
            }, 300);
            vm.isInputFocused = false;
        }
    }
})

到这里就制作完了,如需下载代码,请前往:Vue制作良好交互的信用卡表单

上一篇 下一篇

猜你喜欢

热点阅读