Vue自定义滚动条盒子

应用开发过程中当web页面的内容过多时则会出现滚动条,而原生的滚动条的样式除了谷歌浏览器外其他的浏览器都不好修改,于是打算自己写一个容器组件,当内容过多时隐藏默认的滚动条显示自定义滚动条(只做了垂直滚动条,懒~)

先来看看如何引用这个滚动盒子(hd-scroll,注:"hd"是与我相关某个名字的简称)组件,先在app里面填充100个div:

1 <template>
2     <div class="container">
3         <div v-for="i in 100" :key="i">{{ i }}</div>
4     </div>
5 </template>

然后在把container容器的大小限制一下:

1 <style lang="scss" scoped>
2     .container {
3         background-color: whitesmoke;
4         width: 200px;
5         height: 400px;
6     }
7 </style>

打开页面,可以看到浏览器右边出现了默认的滚动条,而且我们添加的div元素也超出了container范围。

解决这个问题的一般方式是在样式里面添加“overflow:auto”属性,再来看一下效果:

改善了许多,但是滚动条的样式却不好改变,于是现在引入hd-scroll组件:

 1 <template>
 2     <div class="container">
 3         <hd-scroll>
 4             <div v-for="i in 100" :key="i">{{ i }}</div>
 5         </hd-scroll>
 6     </div>
 7 </template>
 8
 9 <script>
10 import hdScroll from ‘./components/hdScroll‘
11
12 export default {
13     components: {
14         hdScroll
15     }
16 }
17 </script>
18
19 <style lang="scss" scoped>
20     .container {
21         background-color: whitesmoke;
22         width: 200px;
23         height: 400px;
24     }
25 </style>

在这里需要注意的是用<hd-scroll>标签来包裹住大量的要渲染的元素,同时删除overflow属性,添加了滚动盒子组件后的页面看起来或许是这个样子的:

ps:鼠标的小黄点是录频工具的,不是页面自带的。。。

滚动盒子(hd-scroll)的实现方式如下:

  1 <template>
  2     <div class="hd-scroll scrollbox" ref="box"
  3     @mousewheel.stop.prevent="handleMouseWheel"
  4     @mouseenter="handleMouseEnter"
  5     @mouseleave="handleMouseLeave">
  6         <transition name="fade">
  7             <div :class="[‘scrollbar‘, { force: force }]" ref="bar"
  8             v-show="show" :style="{ ‘height‘: barHeight + ‘px‘}"
  9             @mousedown="handleMouseDown"></div>
 10         </transition>
 11         <slot></slot>
 12     </div>
 13 </template>
 14
 15 <script>
 16 export default {
 17     name: ‘hdScroll‘,
 18     data() {
 19         return {
 20             box: undefined, // 自定义滚动条盒子
 21             bar: undefined, // 滚动条
 22             barHeight: 100, // 滚动条高度
 23             ratio: 1,       // 滚动条偏移率
 24             force: false,   // 滚动条是否被鼠标光标按住
 25             hover: false,   // 鼠标光标是否悬停在盒子上
 26             show: false     // 是否显示滚动条
 27         }
 28     },
 29     mounted() {
 30         this.box = this.$refs.box
 31         this.bar = this.$refs.bar
 32         // 滚动条全局可拖动
 33         document.addEventListener(‘mouseup‘, this.handleMouseUp)
 34         document.addEventListener(‘mousemove‘, this.handleMouseMove)
 35     },
 36     methods: {
 37         /**
 38          * 鼠标滚轮事件
 39          * @param {object} e 事件
 40          */
 41         handleMouseWheel(e) {
 42             this.box.scrollTop -= e.wheelDelta / 4
 43             this.bar.style.transform = ‘translateY(‘ + (this.box.scrollTop + this.box.scrollTop / this.ratio) + ‘px)‘
 44         },
 45         /**
 46          * 鼠标按下
 47          * @param {object} e 事件
 48          */
 49         handleMouseDown(e) {
 50             if (e.target === this.bar) {
 51                 this.box.prevY = e.pageY
 52                 this.force = true
 53             }
 54         },
 55         /**
 56          * 鼠标按键释放
 57          */
 58         handleMouseUp() {
 59             this.force = false
 60             this.box.prevY = null
 61             if (!this.hover) {
 62                 this.show = false
 63             }
 64         },
 65         /**
 66          * 鼠标移动
 67          * @param {object} e 事件
 68          */
 69         handleMouseMove(e) {
 70             if (this.force) {
 71                 // 阻止默认选中事件(IE下无效)
 72                 e.preventDefault()
 73                 this.box.scrollTop += (e.pageY - this.box.prevY) * this.ratio
 74                 this.bar.style.transform = ‘translateY(‘ + (this.box.scrollTop + this.box.scrollTop / this.ratio) + ‘px)‘
 75                 this.box.prevY = e.pageY
 76             }
 77         },
 78         /**
 79          * 鼠标光标进入盒子范围
 80          */
 81         handleMouseEnter() {
 82             this.hover = true
 83             if (this.box.scrollHeight > this.box.offsetHeight) {
 84                 // 修正进度条高度和位置(建议通过事件触发)
 85                 this.barHeight = this.box.offsetHeight ** 2 / this.box.scrollHeight
 86                 this.ratio = (this.box.scrollHeight - this.box.offsetHeight) / (this.box.offsetHeight - this.barHeight)
 87                 this.bar.style.transform = ‘translateY(‘ + (this.box.scrollTop + this.box.scrollTop / this.ratio) + ‘px)‘
 88                 // 显示滚动条
 89                 this.$nextTick(() => this.show = true)
 90             }
 91         },
 92         /**
 93          * 鼠标光标离开盒子范围
 94          */
 95         handleMouseLeave() {
 96             this.hover = false
 97             if (!this.force) {
 98                 this.show = false
 99             }
100         }
101     }
102 }
103 </script>
104
105 <style lang="scss" scoped>
106     // 滚动条宽度
107     $scrollbar-width: 8px;
108
109     .scrollbox {
110         width: 100%;
111         height: 100%;
112         position: relative;
113         padding-right: $scrollbar-width;
114         overflow-y: hidden;
115     }
116     .scrollbar {
117         width: $scrollbar-width;
118         height: 100%;
119         background-color: darkgray;
120         position: absolute;
121         right: 0;
122         border-radius: $scrollbar-width / 2;
123         &:hover {
124             background-color: gray;
125         }
126         &.force {
127             background-color: gray;
128         }
129     }
130
131     // Vue进入离开动画
132     .fade-enter-active, .fade-leave-active {
133         transition: opacity .5s;
134     }
135     .fade-enter, .fade-leave-to {
136         opacity: 0;
137     }
138 </style>

在谷歌里鼠标滚轮事件可使用deltaY来控制滚动,不过为了兼容ie,选择了使用wheelDelta来代替,它们之间的关系大约是wheelDelta == -4 * deltaY。在设置滚动条移动的过程中是通过CSS3属性transform,在低版本ie浏览器中可能无法运行,可以考虑使用style.top来代替,不过看网上大神们都是通过两个div容器来隐藏主默认的滚动条,实现方法如下:

 1 <!DOCTYPE html>
 2 <html lang="zh-CN">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 7     <title>Document</title>
 8     <style>
 9         #app {
10             width: 200px;
11             height: 400px;
12         }
13     </style>
14 </head>
15 <body>
16     <div id="app">
17         <div class="out-box">
18             <div class="inner-box">
19                 <div class="container">
20                     <div v-for="i in 100" :key="i">{{ i }}</div>
21                 </div>
22             </div>
23         </div>
24     </div>
25     <script src="./vue.min.js"></script>
26     <script>
27         new Vue({
28             el: ‘#app‘
29         })
30     </script>
31 </body>
32 </html>

先设置好页面结构,在这里#app是宽度200px, 高度400px的容器,我们需要使内容不溢出的同时隐藏滚动条:

 1 .out-box {
 2     width: 100%;
 3     height: 100%;
 4     position: relative;
 5     overflow: hidden;
 6 }
 7
 8 .inner-box {
 9     width: 100%;
10     height: 100%;
11     position: absolute;
12     padding-right: 17px;
13     padding-bottom: 17px;
14     overflow: auto;
15 }

只需要添加两个盒子属性就完成了,很简单吧

源码下载(需要自己装包):https://files.cnblogs.com/files/viewts/hd-scroll.zip

原文地址:https://www.cnblogs.com/viewts/p/11170517.html

时间: 2024-07-31 23:42:22

Vue自定义滚动条盒子的相关文章

vue 自定义 滚动条指令

Vue.directive('scroll', { bind: (el, binding, vnode) => { // 是否执行回调事件 let eventAction = true // 距离底部剩余距离开始触发回调 let distance = 100 // (unit: px) // 监听滚动事件 el.onscroll = (e) => { binding.value() } } }) 原文地址:https://www.cnblogs.com/tutao1995/p/12096442

自定义滚动条和拖拽

实现自定义滚动条和拖拽滚动效果 <div class="dropDownMenu"> <ul> <li><a href="#">平缝机</a></li> <li><a href="#">包缝机</a></li> <li><a href="#">绷缝机</a></li&

H5自定义滚动插件——DeftScroll.js,可自定义滚动条

在一些项目中,用户总是要求自定义一下滚动条,以前一般用iscroll解决,但是发现iscroll有很多不方便的地方,而且也比较大,索性自己琢磨一个类似的插件吧!目的有两个:要足够小,易于上手使用:功能一定要足够实用,能满足广大H5开发者的基本需求. 介绍一下这个插件的主要功能: 1.隐藏或显示滚动条,自定义滚动条样式. 2.滚动dom的刷新:refresh: 3.滚动内容的懒加载: 4.子元素绑定tap事件: 5.支持scrolling.scrollEnd等插件内事件绑定: 6.scrollTo

利用CSS3新特性实现完全兼容的自定义滚动条。

背景:最近项目里面因为统一页面风格,用到了自定义滚动条,在完成之前的那个滚动条的时候,与网上各个滚动条插件实现的方法类似,相当于造了轮子,通过css3的 网上看到的滚动条插件多数是通过监听内容的滚动事件,由于原生js的滚动事件存在一些bug,所以实际上用jQuery的mousewheel.js插件的比较多,自己做的滚动条也是引用了该插件. 首先说一说自定义滚动条实现的普遍步骤和方法: 背景: A需要滚动. 1.给A添加一个父级S包裹,并将B进行绝对或相对定位(这点根据S的定位,目的是为了保持原有

iPhone手机解锁效果&amp;&amp;自定义滚动条&amp;&amp;拖拽--Clone&amp;&amp;窗口拖拽(改变大小/最小化/最大化/还原/关闭)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

CSS自定义滚动条样式

相信很多人都遇到过在设计中自定义滚动条样式的情景,之前我都是努力说服设计师接受浏览器自带的滚动条样式,但是这样只能规避还是解决不了问题,最近在项目中遇到了,正好来总结一下.当然,兼容所有浏览器的滚动条样式目前是不存在的. IE下的滚动条样式 IE是最早提供滚动条的样式支持,好多年了,但是其它浏览器一直没有支持,IE独孤求败了. 这些样式规则很简单: scrollbar-arrow-color: color; /*三角箭头的颜色*/ scrollbar-face-color: color; /*立

自定义滚动条

<!DOCTYPE HTML><html><head><title>自定义滚动条</title><meta charset="UTF-8"><link rel="stylesheet" href="reset.css" type="text/css" /><script type="text/javascript" s

vue自定义指令(Directive中的clickoutside.js)的理解

.array p { counter-increment: longen; margin-left: 10px } .array p::before { content: counter(longen) "." } .alink { font-size: 16px; color: blue } 阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DO

移动端网页自定义滚动条

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta id="viewport" name="viewport" content="initial-scale=1.0,user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <title&