随心所欲的滚动条,远离产品汪(二)

还记得上周咱们说的“随心所欲滚动条,远离产品汪”一文吗?当中介绍了自定义滚动条的基本原理与实现方法,在自定义滚动条实现后,可以通过对滚动条的上下拖动来控制内容区的显示,使用过的朋友会发现,如果对篇幅较长的内容来说,不停的拖动滚动条来查看内容,还是比较麻烦的,于是本文在上篇代码的基础上添加了滚轮事件并处理了相应的兼容问题。

本文内容

1、原理结构图

2、滚轮事件及兼容问题概要

3、具体实现步骤

4、小结

原理结构图

为了方便大家熟悉理解,希望大家能够回顾下上篇“随心所欲滚动条,远离产品汪(一)”,本文继续使用了上篇文章的原理结构图来辅助理解。

滚轮事件及兼容问题概要

在鼠标上,除了点击、拖拽等事件,当然也少不了滚轮事件了,但是比较有意思的一点是,平常大家碰到兼容问题首先想到了IE这个万年背锅侠,但是这次还真不是,火狐别树一帜的凑了一回热闹。

1.在滚轮事件中,火狐的的滚动事件是DOMMouseScroll,而其它浏览器是mousewheel,这一点是要仔细留意的。

2.在事件对象的兼容中。谷歌及主流浏览器的事件对象为参数e,而ie事件对象是window.event

3.当滚动鼠标的时候,火狐浏览器通过检测datail的正负号就可以确定, 而其它浏览器IE、谷歌通过检测wheelDelta正负来确定。

具体实现步骤

滚动事件的添加原理其实与实现自定义滚动条的原理基本一致,只是多了滚轮滚动方向的判断及滚动值的获取。

首先,我们需要明白我们的滚轮是作用在谁的身上,根据实际需求来进行事件绑定,当我们鼠标移入可视区时,会触发滚轮事件,在移出可视区时则清除滚轮事件,接下来进行具体代码操作。

ps:此处为了方便理解使用jQuery来实现,记得引入呦。

较之上篇的实现代码,本篇中增加了两个变量。

1.通过设置变量Judge来判断滚轮的滚动方向,当Judge为ture时,滚轮向上滚动,当Judge为false时,滚轮向下滚动。

2.设置变量scrY来存储当前的滚动值,用来计算滚动块的scrollTop值。

步骤一:给可视区A绑定事件

var srcY = 0;
$('#cn').hover(function(e){ // 移入可视区A        
        $('#cn').on('mousewheel DOMMouseScroll', function(e) {
            e = e.originalEvent || window.event.originalEvent; //绑定事件对象
            scrollFunc(e); //执行scrollFunc(),判断滚动方向
            var c = $('#cn').height() - $('#bx').height();    
            if (Judge) { // 当滚动向上滚动时,scrY递减
                scrY--;
            }else{
                scrY++;// 当滚动向下滚动时,scrY递增
            }
            if (scrY <= 0) { //向上滚动的最大值
                scrY = 0;
            }    
            if (scrY >= c) {//向下滚动的最大值
                scrY = c;
            };
            bx.scrollTop = scrY*10; //为防止滚轮滚动速度过慢,所以乘10增加滚轮滚动速度
            sc.style.top =bx.scrollTop*bxHeight/cnHeight + "px";//与滚动条绑定
        })        
    }, function(){//鼠标移出可视区A
        //移除滚动事件
        $('#cn').off('mousewheel DOMMouseScroll');


    })

步骤二:判断滚轮滚动方向

var Judge = true;
function scrollFunc(e){//判断滚动方向
    if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件            
        if (e.wheelDelta > 0) { //当滑轮向上滚动时
            Judge = true;
        }
        if (e.wheelDelta < 0) {
            //当滑轮向下滚动时
            Judge = false;
        }
    } else if (e.detail) { //Firefox滑轮事件
        if (e.detail> 0) { //当滑轮向上滚动时
            Judge = false;
        }
        if (e.detail< 0) { //当滑轮向下滚动时
         Judge = true;
        }
    }
}

完整实现代码

完整的实现代码在之前实现滚动条的基础代码上添加,并未做调整,大家可以很轻易的分清区别之处,方便大家理解,之后可以根据自己实际需求在这基础下进行代码优化与封装。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>自定义滚动条(2)</title>
        <style type="text/css">
        .wrap {
            width: 200px;
            height: 150px;
            margin: 0 auto;
        }
        .con {
            float: left;
            overflow: hidden;
            width: 180px;
            height: 150px;
            background: #39f;
        }
        .con p {
            margin: 0;
            color: #fff;
            text-align: center;
            line-height: 20px;
            font-size: 14px;
        }
        .boxscr {
            float: right;
            position: relative;
            width: 20px;
            height: 150px;
            background: #d9ecff;
        }
        .scr {
            position: absolute;
            width: 20px;
            border-radius: 10px;
            background: #c6ccff;
            cursor: pointer;
        }
    </style>
    </head>
    <body>
        <div class="wrap">
            <div class="con" id = "bx">
                <p id="cn">
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                </p>
            </div>
            <div class="boxscr" id = "bs">
                <div class="scr" id = "sc"></div>
            </div>
        </div>
<script src="jquery.js" type="text/javascript"></script>
<script>
    var bx = document.getElementById("bx"),
        cn = document.getElementById("cn")
        bs = document.getElementById("bs"),
        sc = document.getElementById("sc"),


        oldY = 0,     // 鼠标初次点击的Y轴坐标
        newY = 0,     // 鼠标拖动时的Y轴坐标
        nowY = 0,     // 鼠标拖动时滚动条C距父级顶部的高度
        maxY = 0,     // 拖动的最大极限值
        nowDisY = 0, // 点击滚动条C时距父级顶部的高度
        judge = 0,     // 判断鼠标滚轮的方向
        scrY = 0;     // 滚轮滚动距离


        bxHeight = bx.clientHeight, // 可视区A高度
        bsHeight = bs.clientHeight, // 滚动区D高度
        cnHeight = cn.offsetHeight; // 滚动块B的高度


        // 根据滚动块B实际内容高度控制滚动条C的高度
        scHeight = bxHeight/cnHeight * bxHeight;
        sc.style.height = scHeight + "px";


        // 当滚动块B实际高度小于可视区时,滚动条隐藏
        if (cnHeight < bxHeight) {
            bs.style.display = "none";
        };


        sc.onmousedown = function(e) {
            oldY = e.clientY;
            nowDisY = sc.offsetTop;         // 当前的滚动条C的top值
            e.preventDefault();
            document.onmousemove = function(e) {
                newY = e.clientY;
                nowY = nowDisY + newY - oldY; // 拖动后的滚动条C的top值
                maxY = bsHeight - scHeight;    // 设置滚动条top极限值


                if (nowY <= 0) {
                    nowY = 0;
                };
                if (nowY >= maxY) {
                    nowY = maxY;
                };


            bx.scrollTop = nowY/maxY * (cnHeight - bxHeight); // 设置滚动块B的scrollTop值
            sc.style.top = nowY + "px";
            }
 
        }
        document.onmouseup = function() {
            document.onmousemove = null;
        }




        $('#cn').hover(function(e){                                // 移入可视区A        
            $('#cn').on('mousewheel DOMMouseScroll', function(e) {
                e = e.originalEvent || window.event.originalEvent; //绑定事件对象
                scrollFunc(e);                                     //判断滚动方向
                var c = $('#cn').height() - $('#bx').height();    
                if (Judge) {
                    scrY--;
                }else{
                    scrY++;
                }
                if (scrY <= 0) {
                    scrY = 0;
                }    
                if (scrY >= c) {
                    scrY = c;
                };
                bx.scrollTop = scrY*10;        
                sc.style.top =bx.scrollTop*bxHeight/cnHeight + "px";
            })        
        }, function(){ //鼠标移出可视区A
            //移除滚动事件
            $('#cn').off('mousewheel DOMMouseScroll');


        })
        //判断滚动方向
        function scrollFunc(e){        
            if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件            
                if (e.wheelDelta > 0) { //当滑轮向上滚动时
                    Judge = true;
                }
                if (e.wheelDelta < 0) {
                    //当滑轮向下滚动时
                    Judge = false;
                }
            } else if (e.detail) { //Firefox滑轮事件
                if (e.detail> 0) { //当滑轮向上滚动时
                    Judge = false;
                }
                if (e.detail< 0) { //当滑轮向下滚动时
                 Judge = true;
                }
            }
        }        
        </script>
    </body>
</html>

实现效果:

小结

到此为止,自定义滚动条的实现已基本完成,其中主要掌握滚动位置的偏移方式及相似比计算便可迎刃而解,同时滚轮事件的兼容问题也是不可忽视的,虽然麻烦了一丢丢,但是只要理清思路,解决起来还是简单的。

本文系HTML5学堂独家内容,转载请在文章开头显眼处注明作者和出处“HTML5学堂(http://www.h5course.com/)”

原文发布于微信公众号 - HTML5学堂(h5course-com)

原文发表时间:2016-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏web前端

制作H5响应式页面注意事项、微信二次分享

1、H5页面(APP端)      1.1     APP端页面用HTML5制作,头部需要加适配信息:   <meta http-equiv="Content-...

2979
来自专栏cnblogs

CSS3新特性应用之用户体验

一、光标 新增加not-allowed光标,不允许访问 隐藏光标,在触模应用上很有用,css2.1需要一个透明的图片来实现,而css3直接用cursor:non...

2018
来自专栏HTML5学堂

CSS3实现loading图

HTML5学堂:学习CSS3,重要的并不是那几个命令,而是如何应用CSS3的知识实现网站中的效果,换句话说,“只有想不到,没有做不到”。在这个效果当中,主要用到...

3894
来自专栏HTML5学堂

HTML知识复习

HTML5学堂:本篇文章主要是从头到尾串一下HTML4.0的知识点。很多知识在网站各个文章中都已经讲解过了,在这里就不再重复书写了。学习时,知识点固然重要,但是...

2984
来自专栏九彩拼盘的叨叨叨

学习纲要:常见标签和属性

802
来自专栏编程

前端学习自学笔记:day06

今天是第六天的笔记,主要是HTML和CSS的,希望大家支持~ ? 在此之前先为大家显示下前端工程师的路线图: ? 第六天的笔记:HTML AND CSS: te...

1915
来自专栏前端说吧

css笔记 - 张鑫旭css课程笔记之 overflow 篇

如果overflow-x、overflow-y的值相同,则等同于overflow设置了这个值。

781
来自专栏web前端

制作H5响应式页面注意事项、微信二次分享

          1.2.1     重要的图片用img标签(例如头部banner等包含特定信息的内容图片),不重要的底板用背景形式显示,例如底部背景

1590
来自专栏前端说吧

css布局 - 垂直居中布局的一百种实现方式(更新中...)

1. line-height行高简单粗暴实现法:line-height:Npx(N = 与元素高度相同的值)

2741
来自专栏前端新视界

两个 viewports 的故事-第二部分

原文:A tale of two viewports — part two 译者:nzbin 在这个迷你系列中,我将解释 viewports 和各种重要元素...

1867

扫码关注云+社区