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

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

本文内容

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 条评论
登录 后参与评论

相关文章

来自专栏Coco的专栏

谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

815
来自专栏web前端-

HTML基础知识

  属性的作用就是就为元素提供更多的信息,大多数元素都可以拥有属性    属性的语法:<标签 属性1=参数1>   注意空格的使用

543
来自专栏柠檬先生

css3基础知识——回顾

1.属性选择器 完全匹配的属性选择器 [id=article]{}     示例:       <style>         input[typ...

1987
来自专栏小古哥的博客园

读书笔记《CSS权威指南》

阅读本书主要目的: 自从学会CSS以来,虽然熟练掌握了其使用方法和技巧,但对其底层的原理和实现并不清晰,阅读本书想进一步系统化的学习和深入研究其本质,对这门前端...

3255
来自专栏腾讯社交用户体验设计

表格边框你知多少

1043
来自专栏小李刀刀的专栏

webkit中BFC元素临近浮动元素时的边距bug

一直以来我们都很熟悉IE的“浮动边距加倍”的bug,并且绝大多数重构人员都已经很擅长在需要浮动时就直接绕过他。其实以webkit为核心的浏览器,包括但不限于Sa...

3035
来自专栏Python研发

CSS

CSS是Cascading Style Sheets的加简称,中文称为层叠样式表,用来控制网页数据的表现,可以使网页的表现与数据内容分离。

663
来自专栏十月梦想

渐变与文本格式化属性

background-image:linear-gradient(angle,color,color);

594
来自专栏我分享我快乐

WEB布局基础知识点图解

581
来自专栏前端杂货铺

翻译:如何使用CSS实现多行文本的省略号显示

本文翻译自CSS Ellipsis: How to Manage Multi-Line Ellipsis in Pure CSS,文中某些部分有些许改动,并添...

3396

扫描关注云+社区