自定义滚动条


前言

甲方爸爸要求的太多了!!!在此强烈谴责!!!(只能在这里谴责了)。
需求: 在左侧显示文本内容,如果有高亮的文本,要在右侧的滚动条对应的位置展示高亮颜色。
**思路:**先实现滚动条样式以及功能,在滚动条内添加对应的div,需要遍历两次,第一次遍历的是文本高亮的行数;第二次遍历的是滚动条的对应行数的div,并给div上颜色。(如果有更好的办法,请私信我,或者评论区评论一下,谢谢~)
下面的代码仅仅实现滚动条功能,高亮还有添加,不过自己可以设置滚动条和滑块的样式,应付一般的需求,应该够了。后续会完善高亮部分
在这里插入图片描述


一、实现html 和css样式

先把样式搞出来

<template>
    <div class="scrollbar">
        <div class="scrollbar-content">
            <ul class="box" id="box">
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>21111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>11111</li>
                <li>33333</li>
                /**其他文本**/
            </ul>
        </div>
        <div class='scrollbar-bar' id="scrollbar-bar" :style="{height:scrollbarHeight+'px'}">
            <div class="scrollbar-thumb" id="scrollbar-thumb"></div>
        </div>
    </div>

二、js部分

现在来用js操作DOM节点
代码如下(示例):

		//data内容
		data(){
        	return {
	             scrollbarHeight:0,//滚动条的高度
	             contentHeight:0,//内容的高度
        	}
    	},

		//methods内容:
		//设置滚轮的高度
        setScrollHeight(){
            // 获取文本的高度
            let totalHeight = 0
            let listItems = document.querySelectorAll('li')
            listItems.forEach(element => {
                totalHeight += element.offsetHeight
            });
            this.contentHeight = totalHeight
            // 设置滚轮的高度
            let height = document.querySelector('.scrollbar-thumb')
            height.style.height = 400 / totalHeight * 400 + 'px'
            // 设置滚动条高度
            let divTarget = document.querySelector('.scrollbar-content')
            this.scrollbarHeight = divTarget.offsetHeight
        },
        
        // 设置滚动条滑动事件
        scrollBarEvent(){
            let _this = this
            // 获取要绑定事件的 div 元素
            let scrollContainer = document.getElementById('scrollbar-bar');//滚动条容器
            let scrollHandle = document.querySelector('#scrollbar-thumb');//滑块
            let textBox = document.getElementById('box')//文本节点
            //移动事件
            window.addEventListener('wheel',function(event){
                const delta = event.deltaY; // 获取鼠标滚轮的滚动距离
                const currentPosition = parseInt(scrollHandle.style.top) || 1; // 获取当前span的top值,默认为1px
                // 确保span元素不超出container的范围
                let maxTop = scrollContainer.clientHeight - scrollHandle.clientHeight;
                let newPosition = currentPosition + delta; // 计算新的位置
                newPosition = Math.min(Math.max(newPosition,0),maxTop)
                scrollHandle.style.top = newPosition + 'px'; // 更新top值

                // 计算文本内容的偏移量
                let barSpeed = newPosition / _this.scrollbarHeight
                let distance = _this.contentHeight * barSpeed
                textBox.style.top = -distance + 'px'; // 更新文本内容的展示位置
            })
        },

更新内容,完善后续功能。

三、完整代码(后续补充,已完结)


<template>
    <div class="scrollbar">
        <div class="scrollbar-content">
            <ul class="box" id="box">
                <li :class="item%2===0?'li-background':''" v-for="item in 53" :key="item" :id="item">{{ item }}</li>
            </ul>
        </div>
        <!-- 滚动条 -->
        <div class='scrollbar-bar' id="scrollbar-bar" :style="{ height:scrollbarHeight + 'px'}">
            <div class="scrollbar-thumb" id="scrollbar-thumb"></div>
        </div>
        <!-- 滚动条高亮展示区域 -->
        <div id="container-light" class="container-color" :style="{ height:scrollbarHeight + 'px'}">
            <div 
            style="height:2px;" 
            :class="item%2===0?'li-background':''" 
            v-for="item in list" :key="item" 
           >
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return {
             scrollbarHeight:0,//滚动条的高度
             contentHeight:0,//内容的高度
             list:53,
             scrollContainer:null,//滚动条容器
             scrollHandle:null,//滑块
             textBox:null,//文本节点
        }
    },
    mounted(){
        this.setScrollHeight()
        this.scrollBarEvent()
        this.scrollClickEvent()
    },
    
    methods:{
        /**
         * 初始化数据
         */
        setScrollHeight(){
            // 获取文本的高度
            let totalHeight = 0
            let listItems = document.querySelectorAll('li')
            listItems.forEach(element => {
                totalHeight += element.offsetHeight
            });
            this.contentHeight = totalHeight
            // 设置滚轮的高度
            let height = document.querySelector('.scrollbar-thumb')
            height.style.height = 400 / totalHeight * 400 + 'px'
            // 设置滚动条高度
            let divTarget = document.querySelector('.scrollbar-content')
            this.scrollbarHeight = divTarget.offsetHeight
        },
        
        /**
         * 设置滚动条滑动事件
         */
        scrollBarEvent(){
            // 获取要绑定事件的 div 元素
            this.scrollContainer = document.getElementById('scrollbar-bar');//滚动条容器
            this.scrollHandle = document.querySelector('#scrollbar-thumb');//滑块
            this.textBox = document.getElementById('box')//文本节点
            //滑轮滚动监听事件
            window.addEventListener('wheel',this.removeEntity)
        },

        /**
         * 滚动条点击事件
         */
        scrollClickEvent(){
            let _this = this
            let scrollContainer = document.getElementById('container-light');//滚动条容器
            let topDistance = 0
            scrollContainer.addEventListener('click',e=>{
	            topDistance = _this.scrollHandle.getBoundingClientRect()
	            _this.scrollBarRemove({ deltaY: e.clientY })
            })
        },

        /**
         * 滚轮滚动回调事件
         * @param event 位置信息
         */
        removeEntity(event){
            const delta = event.deltaY; // 获取鼠标滚轮的滚动距离
            const currentPosition = parseInt(this.scrollHandle.style.top) || 1; // 获取当前span的top值,默认为50px
            // 确保span元素不超出container的范围
            let maxTop = this.scrollContainer.clientHeight - this.scrollHandle.clientHeight;
            let newPosition = currentPosition + ( delta ); // 计算新的位置
            newPosition = Math.min(Math.max(newPosition,0),maxTop)
            this.scrollHandle.style.top = newPosition + 'px'; // 更新top值

            // 计算文本内容的偏移量
            let barSpeed = newPosition / this.scrollbarHeight
            let distance = this.contentHeight * barSpeed
            this.textBox.style.top = -distance + 'px'; // 更新文本内容的展示位置
        },

        /**
         * 单击滚动条,滑块定位到当前位置,文本按比例定位到所在位置
         * @param event 位置
         */
        scrollBarRemove(event){
            // 滚动条高度
            let scrollBar = Number(this.scrollHandle.style.height.split('px')[0])
            let top = event.deltaY - scrollBar / 2
            let height = event.deltaY + scrollBar
            if (height > this.scrollbarHeight) {
                this.scrollHandle.style.top = this.scrollbarHeight - scrollBar + 'px'
                this.textBox.style.top = -this.contentHeight + 420 + 'px'; //这里420是文本的高度,根据自身的需求,应设置为动态的。
            }else if(event.deltaY < scrollBar / 2){
                this.scrollHandle.style.top = 0 + 'px'
                this.textBox.style.top = 0 + 'px';
            }else{
                this.scrollHandle.style.top = top + 'px'
                let barSpeed = top / this.scrollbarHeight
                let distance = this.contentHeight * barSpeed
                this.textBox.style.top = -distance + 'px';
            }
        }
    }
}
</script>

<style scope>
.scrollbar{
    height: 400px;
    border: black 2px solid;
}
.scrollbar-content{
    height:100%;
    border: red 1px solid;
    overflow: hidden;
}

.scrollbar-bar{
    height: 100%;
    width: 20px;
    background-color: #fff;
    position: absolute;
    top: 0;
    right: 0;
}

.scrollbar-thumb{
    height: 50px;
    width: 100%;
    background-color: rgba(162, 161, 163, 0.5);
    border: 1px solid rgba(162, 161, 163, 0.2);
    position: absolute;
    top: 0;
    right: 0px;
    transition: all 0.5s linear;
}

.box{
    position: relative;
    top: 0;
    right: 0;
}

.container-color{
    height: 100%;
    width: 20px;
    position: absolute;
    top: 0;
    right: 0px;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
}
.li-background{
    background-color: yellow;
}
</style>

效果图
没有点击前
在这里插入图片描述
点击后
在这里插入图片描述

四、更新代码(方法二)

新的思路:新建一个div,div里面是高亮条,让div的长度和原生滚动条长度一样,在使用绝对定位放到滚动条上面,使两者重合,滚动条设置在最上面,然后再设置滚动条背景色是透明的,滑块设置半透明,就可以达到上述图片的效果了
完结撒花花花~

总结

多读书,多看报,少吃零食,多睡觉。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值