スライディングスケールのフロントエンド実装

フロントエンドはスライディングスケール効果を実装しています。スケールを左右にスライドすると、対応するデータが変化します。効果は次のとおりです:

実装のアイデア: データ バインディングには vue2 を使用し、上記のデータがリアルタイムで更新されるようにします。スケールを右にスライドすると値が増加し、左にスライドすると減少します。

1. 幅と高さが固定された大きな div ボックスを作成します。

2. 外側の div に div をネストし、親 div ボックスを超える幅を設定し、子ボックスの背景画像としてスケールの png 画像を作成し、親にscroll-y:autoを設定します。左へ 右にスワイプ

3. 参照オブジェクトとして青いポインタである小さな div を書き込み、親フェーズの中央に配置します。

4. jsメソッドは、親ボックスの左右にスライドするスクロールバーを監視し、ビュー内の番号に割り当てることで、スライディングスケールの変更を実現します。

具体的なコードの実装は次のとおりです。

<template>
    <div class="loginTwo">
        <div class="head">
            <van-nav-bar title="完善信息" />
        </div>
        <div class="main">
            <div class="form">
                <p class="title">你的身高</p>
                <div class="box">
                    <div class="text textA">{
   
   { height }}</div>
                    <div class="outBox" ref="h_out" @scroll="handleHeight">
                        <div class="liningBox" ref="h_lin"></div>
                    </div>
                    <!-- 基准线 -->
                    <div class="vertical"></div>
                </div>
                <p class="title">你的体重</p>
                <div class="box2">
                    <div class="text textB"> {
   
   { weight }}</div>
                    <div class="outBox" ref="out" @scroll="handleWeight">
                        <div class="liningBox" ref="lin"></div>
                    </div>
                    <!-- 基准线 -->
                    <div class="vertical2"></div>
                </div>
                <div class="btn">下一步</div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            w_scroll: 0,
            h_scroll: 0,
        }
    },
    mounted() {
        this.$refs.out.scrollLeft = 300;
        this.$refs.out.addEventListener('scroll', this.handleScroll, { passive: true });
        this.$refs.h_out.scrollLeft = 300;
        this.$refs.h_out.addEventListener('scroll', this.handleScroll, { passive: true });
    },
    computed: {
        weight() {
            if (this.w_scroll <= 30) {
                return 30
            } else {
                return this.w_scroll
            }
        },
        height() {
            if (this.h_scroll <= 30) {
                return 30
            } else {
                return this.h_scroll
            }
        }
    },
    methods: {
        handleWeight() {
            const scrollLeft = this.$refs.out.scrollLeft;
            const w_distance = this.getFractionalScroll(scrollLeft, 1) * 200;
            this.w_scroll = w_distance.toFixed(1)
        },
        handleHeight() {
            const scrollLeft = this.$refs.h_out.scrollLeft;
            const h_distance = this.getFractionalScroll(scrollLeft) * 300;
            this.h_scroll = Math.round(h_distance)
        },
        getFractionalScroll(scrollLeft, val) {
            if (val == 1) {
                const scrollWidth = this.$refs.out.scrollWidth - this.$refs.out.clientWidth;
                const fractionalScroll = scrollLeft / scrollWidth;
                // return fractionalScroll.toFixed(3); // 设置小数点位数
                return fractionalScroll; // 设置小数点位数
            } else {
                const scrollWidth = this.$refs.h_out.scrollWidth - this.$refs.h_out.clientWidth;
                const fractionalScroll = scrollLeft / scrollWidth;
                return fractionalScroll; // 设置小数点位数
            }

        },
    },
}
</script>
<style lang="scss" scoped>
.head {
    // padding-top: 20px;
    height: 150px;
    width: 100%;
    background-color: #5B74FF;
}

.head::v-deep .van-nav-bar {
    background-color: transparent;
}

::v-deep .van-nav-bar__title {
    color: #ffffff;
    font-weight: bold;
    font-size: 18px;
}

::v-deep.van-hairline--bottom::after {
    border-bottom-width: 0,
}

.main {
    height: calc(100vh - 90px);
    background-color: #ffffff;
    position: relative;
}

.form {
    position: absolute;
    border-radius: 0 50px 0 0;
    background-color: #ffffff;
    top: -8%;
    height: 100%;
    width: 100%;
    padding: 32px 18px 0;
}

.title {
    font-size: 18px;
    font-weight: 800;
    color: #2A2A2A;
    margin-bottom: 23px;
}

.outBox {
    height: 35px;
    overflow-x: scroll;
    position: relative;
}


.liningBox {
    width: 800px;
    height: 35px;
    background: url(../../assets/images/ruler.png)repeat-x;
}

.vertical {
    position: absolute;
    display: block;
    width: 2px;
    height: 40px;
    background-color: #5B74FF;
    left: 48%;
    top: 37.2%;

}

.vertical2 {
    position: absolute;
    display: block;
    width: 2px;
    height: 40px;
    background-color: #5B74FF;
    left: 48%;
    top: 37.2%;

}

.outBox::-webkit-scrollbar {
    display: none;
}

.box {
    padding: 32px 36px 90px;
    text-align: center;
    position: relative;
}

.box2 {
    padding: 32px 36px 90px;
    text-align: center;
    position: relative;
}

.text {
    font-size: 29px;
    font-weight: 800;
    color: #5B74FF;
    margin-bottom: 6px;
}

.textA::after {
    content: 'cm';
    font-size: 12px;
    font-weight: lighter;
    color: #5B74FF;
}

.textB::after {
    content: 'kg';
    font-size: 12px;
    font-weight: lighter;
    color: #5B74FF;
}

.btn {
    width: 300px;
    height: 42px;
    line-height: 42px;
    background: #5B74FF;
    border-radius: 21px;
    text-align: center;
    color: #ffffff;
    font-size: 15px;
    margin: 0 auto 12px;
}
</style>

おすすめ

転載: blog.csdn.net/weixin_51828648/article/details/133361158