HTML自定义滚动条附效果图和完整源码

效果图:

实现过程:

  1. 设置默认的滚动条和滚动条背景


                    <view class="myscrollBlock">
                        <view class="myscrollBg">

                        </view>
                        <view class="myscroll" :style="`width:${scroll_width}rpx;left:${scroll_left}rpx;`">

                        </view>
                    </view>

    .myscrollBlock {
        position: relative;
        width: 100rpx;
        top: -30rpx;
        left: 50%;
        transform: translateX(-50%);

        .myscrollBg {
            width: 100rpx;
            height: 8rpx;
            background: rgba(197, 254, 255, 0.15);
            position: absolute;
            z-index: 2;
            border-radius: 10rpx;
        }

        .myscroll {

            height: 8rpx;
            background: #1CD5CD;
            border-radius: 10rpx;
            position: absolute;
            z-index: 3;
        }
    }

容器实际的总宽度(listWidth) = 容器内元素的(宽度+边距) * 数量

容器现有宽度( blockWidth) = 我的容器现有宽度为屏幕的宽度的百分之90

默认滚动条的宽度(滚动条) = 容器现有宽度 / 容器实际的总宽度 * 100

setMyScrooll() {
   this.scroll_width =0;
   this.scroll_left =0;
   let listWidth = (110+24) * this.list.length
   let blockWidth = uni.getStorageSync('sysTemInfo').screenWidth * 0.9
   this.scroll_width = blockWidth / listWidth * 100
},
  1. 安装vuescroll插件

vuescroll 滚动条插件安装:

npm install vuescroll -S
  1. 根据插件的handleScroll时间,动态获取滚动的进度

handleScroll(vertical, horizontal, nativeEvent) {
                this.scroll_width = horizontal.barSize * 100
                this.scroll_left = (1 - horizontal.barSize) * horizontal.process * 100
            },

注:

1.为了隐藏IOS的默认滚动条,我设置了固定的外层高度,然后overflow: hidden;

2.代码中 vuescroll 组件的高度必须写在view内,因为组件会设置高度为100%,写在css优先级低会导致失效

页面完整代码

<template>
    <view class="page" id="page">
        <image class="xinBj" :src="xinBj"></image>
        <view class="menuBlock">
            <view class="menuItem" v-for="(item, index) in menus" :key="index" @click="chooseMenu(item, index)">
                <view class="titleBlock">

                    <image v-if="item.show" class="menuBgIn" :src="menuIn"></image>
                    <image v-else class="menuBgNo" :src="menuNo"></image>
                    <view class="year" :class="item.show ? 'colorIn' : 'colorNo'" v-html="item.guideNameFull"></view>
                </view>

                <div v-if="item.show" class="offLineTable" style="">
                    <vuescroll class="listBlock" style="height:302rpx;" scrollingY="false" @handle-scroll="handleScroll" :ops="ops">
                        <view class="p_r" v-if="list.length>0">
                            <view class="listItem p_l" v-for="(itemm, indexx) in list" :key="indexx"
                                @click="chooseList(indexx, itemm)"
                                :style="listIdx === indexx ? `background-image:url(${itemBg}); background-repeat:no-repeat; background-size:100% 100%;-moz-background-size:100% 100%;` : ''">
                                <image class="listIcon" :src="listIdx === indexx ? itemm.icon : itemm.icon"
                                    mode="heightFix">
                                </image>
                                <!-- colorIn colorNo-->
                                <view class="txt" :class="listIdx === indexx ? '' : ''">
                                    {
    
    { itemm.guideDetailName }}
                                </view>
                            </view>
                        </view>
                    </vuescroll>
                    <view class="myscrollBlock">
                        <view class="myscrollBg">

                        </view>
                        <view class="myscroll" :style="`width:${scroll_width}rpx;left:${scroll_left}rpx;`">

                        </view>
                    </view>
                </div>
            </view>
        </view>

    </view>
</template>

<script>
    import vuescroll from "vuescroll";
    export default {
        components: {
            vuescroll
        },
        data() {
            return {
                xinBj: this.$config.imageUrl + "xinBj.jpg",
                menuNo: this.$config.imageUrl + "fungusv2/menuNo.png?v=2",
                menuIn: this.$config.imageUrl + "fungusv2/menuIn.png?v=2",
                icon1_1: this.$config.imageUrl + "fungus/icon1_1.png",
                icon1: this.$config.imageUrl + "fungus/icon1.png",
                itemBg: this.$config.imageUrl + "fungusv2/itemBg.png",
                menus: [],
                menuIdx: 0,
                listIdx: 0,
                list: [],
                guideNameFull: "",
                scroll_process: 0,
                scroll_width: 0,
                scroll_left: 0,
                ops: {
                    mode: "slide",
                    locking: true,
                    detectResize: true,
                    sizeStrategy: 'percent',
                    bar: {
                        // rgba(197,254,255,0.15)
                        // "#1CD5CD"
                        background: "#1CD5CD", //滚动条的背景颜色
                        opacity: 0,
                        keepShow: true, // 一直显示滚动条
                        size: '0',
                        // color:"#1CD5CD"
                    },
                    rail: {
                        background: 'rgba(197, 254, 255, 0.15)',
                        opacity: 0,
                        size: '0',
                    },
                    scrollPanel: {},
                }
            };
        },
        onLoad(option) {
            console.log("option.openid");
            if (option.openid) {
                console.log(option.openid);
                uni.setStorageSync("openid", option.openid);
            } else {
                uni.setStorageSync("openid", 123);
            }
            this.menuIdx = 0;
            this.$common.Init.call(this, "");
            // this.setData();
            this.getListFungus();
            console.log(location)
        },

        methods: {
            setMyScrooll() {
                this.scroll_width =0;
                this.scroll_left =0;
                let listWidth = this.list.length * 134
                let blockWidth = uni.getStorageSync('sysTemInfo').screenWidth * 0.9
                this.scroll_width = blockWidth / listWidth * 100
            },
            handleScroll(vertical, horizontal, nativeEvent) {
                this.scroll_width = horizontal.barSize * 100
                this.scroll_left = (1 - horizontal.barSize) * horizontal.process * 100
            },
            getText(str) {
                let words = str.replace(/<[^<>]+>/g, "").replace(/&nbsp;/gi, ""); //这里是去除标签
                return words.replace(/\s/g, ""); //这里是去除空格
            },
            getListFungus() {
                console.log(1);
                this.$request(this.$api.fungus.listFungus).then((res) => {
                    console.log(res);
                    res.data.infos.forEach((item, index) => {
                        if (index == 0) {
                            item.show = true;
                        } else {
                            item.show = false;
                        }
                        if (item.guideDetail) {
                            item.guideDetail.forEach((itemm, indexx) => {
                                itemm.show = false;
                            });
                        }
                    });
                    this.menus = res.data.infos;
                    this.guideNameFull = this.menus[0].guideNameFull;
                    let list = this.menus[0].guideDetail;
                    this.list = list;
                    this.setMyScrooll()

                });
            },
            chooseList(index, item) {
                this.listIdx = index;

                console.log(this.menus[index]);
                console.log(item);
                let params = {
                    first_button: this.getText(this.guideNameFull),
                    second_button: item.guideDetailName,
                };
                this.guidelines(params);
                let url = `/pages/fungusGuide/fungusDetail?guideDetailId=${item.guideDetailId}`;
                this.goOtherPages(url);
            },
            chooseMenu(item, index) {
                this.listIdx = 0;
                if (item.guideDetail) {
                    this.menus.forEach((e) => {
                        e.show = false;
                    });
                    item.show = true;

                    let list = this.menus[index].guideDetail;
                    this.list = list;
                    this.setMyScrooll()
                    this.guideNameFull = this.menus[index].guideNameFull;
                    let params = {
                        first_button: this.getText(this.guideNameFull),
                    };
                    this.guidelines(params);
                } else {
                    uni.showToast({
                        title: "内容开发中, 敬请期待!",
                        icon: "none",
                    });
                }
            },
            guidelines(params) {
                this.$request(
                    this.$api.huoshi.ld_clinical_guidelines_fungus_button,
                    params
                ).then((res) => {
                    console.log(res);
                });
            },
        },
    };
</script>

<style lang="scss">
    .page {}

    .myscrollBlock {
        position: relative;
        width: 100rpx;
        top: -30rpx;
        left: 50%;
        transform: translateX(-50%);

        .myscrollBg {
            width: 100rpx;
            height: 8rpx;
            background: rgba(197, 254, 255, 0.15);
            position: absolute;
            z-index: 2;
            border-radius: 10rpx;
        }

        .myscroll {

            height: 8rpx;
            background: #1CD5CD;
            border-radius: 10rpx;
            position: absolute;
            z-index: 3;
        }
    }

    .colorIn {
        color: #c5feff;
    }

    .colorNo {
        color: #1cd5cd;
    }

    .offLineTable {
        width: 90vw;
        margin-left: 5%;
        height: 290rpx;
        overflow: hidden;
    }

    .listBlock {
        width: 90vw;
        .listItem {
            display: flex;
            flex-shrink: 0;
            width: 228rpx;
            height: 228rpx;
            background: rgba(197, 254, 255, 0.1);
            justify-content: center;
            /*子元素水平居中*/
            align-items: center;
            /*子元素垂直居中*/
            display: -webkit-flex;
            text-align: center;
            margin-right: 20rpx;

            .listIcon {
                height: 74rpx;
            }
        }
    }

    .txt {
        font-size: 26rpx;
        margin-top: 20rpx;
        color: #1cd5cd;
    }

    .menuBlock {
        width: 100vw;
        position: relative;
        padding-top: 20rpx;

        .menuItem {
            margin-bottom: 30rpx;
            padding-bottom: 20rpx;
            width: 100vw;
            position: relative;
            font-size: 32rpx;
            background: rgba(197, 254, 255, 0.05);

            .titleBlock {
                display: flex;
                flex-direction: row;
                padding: 20rpx;
                padding-top: 50rpx;
                padding-bottom: 20rpx;

            }

            .year {
                // margin-top: -10rpx;
                margin-left: 20rpx;
                position: relative;
                z-index: 20;
            }

            .menuBgNo {
                width: 40rpx;
                height: 40rpx;
                z-index: 9;
            }

            .menuBgIn {
                width: 40rpx;
                height: 40rpx;
                z-index: 8;
            }
        }
    }
</style>

猜你喜欢

转载自blog.csdn.net/qq_35713752/article/details/129588798
今日推荐