近期需要改造项目中的滚动条,使原滚动条在三大浏览器下表现相同,分享一下自己的改造经历:

项目中的滚动条分布在网页的各个小窗口中,使用的是-webkit-scrollbar制作,在-webkit内核的浏览器下表现非常漂亮,但是在ie和火狐下无法兼容,还是非常丑的默认样式。

原计划使用css hack打个补丁美化一下,想到ie hack以后变色的默认滚动条,觉得浑身“蓝瘦香菇”。于是决定重写一下这个部分,反正以后用到的地方可以直接拿出来用。

第一次计划打算自己手写,反正逻辑挺简单的,设定个比例拖着走呗

简单代码如下:

    //获取页面元素,有用的元素包括“视框”,“滚动内容”,“滚动条”,“滚动轨迹”
    var box = document.getElementById("box");
    var content = box.children[0];
    var scroll = box.children[1];
    var bar = scroll.children[0];

    //首先要根据box和content的大小比例计算出bar的高
    var bili = box.offsetHeight / content.offsetHeight;
    //用scroll的高乘以比例
    bar.style.height = scroll.offsetHeight * bili + "px";

    //点住滚动条bar,计算鼠标在bar内的位置
    bar.onmousedown = function (e) {
        var y = e.clientY - bar.offsetTop - box.offsetTop;
        //开始拖动
        document.onmousemove = function (e) {
            //获取鼠标的新位置
            var currentY = e.clientY - y - box.offsetTop;
            //需要跟currentY设定上下限
            if (currentY < 0) {
                currentY = 0;
            }
            if (currentY > scroll.offsetHeight - bar.offsetHeight) {
                currentY = scroll.offsetHeight - bar.offsetHeight;
            }
            //设置为bar的top值
            bar.style.top = currentY + "px";
            //取消滚动时的文本选中
            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
            //让文本移动,比例换算。。
            content.style.top = -currentY / bili + "px";
        }
    };

    document.onmouseup = function () {
        document.onmousemove = null;
    }

这样就完了?呵呵别天真了

滚动条的位置如图,滚动条在menu位置滚动是不受任何影响的,一旦移入右侧的ifarme嵌入的窗口就失效了,原因就是上述代码中绑定的document在iframe窗口中也存在。

如何解决这个问题,在网上找了大半天没相关结果,结果一个qq群小伙伴给了个网站document.domain,有了点想法,主要的一点是找到这个iframe,再给这个ifame绑定上事件监听。

关键的一点 $("iframe").contents().find("body").mousemove(function(){  someting to do })

同理当鼠标抬起的时候也绑定到这个上面。

这里注意防止鼠标拖动和鼠标抬起的目标元素不一样导致的bug,要在根document和iframe里的document里面都绑定上事件监听。 呵呵...感觉好傻 (这里的代码已经遗失了,不过很简单,上面的原生的js代码已经被我写成了jQuery的)

如果你只实现一个可以在iframe边缘拖动的滚动条现在已经可以了,但是领导说还要实现滚轮在menu列表上滚动,也可以调用滚动条,想想还是用个插件,可以实现跟多的功能。

 找到的第一款插件是 iscroll     github地址  中文文档地址

 基本的使用在github上就可以看到,但是我当时没有发现设置样式(例如,颜色、宽高的功能)

 于是在源码中做了如下修改

  在1002和1009行做了如下修改

  加了一个参数  this.options.myStyle

el: createDefaultScrollbar('v', interactive, this.options.scrollbars, this.options.myStyle) //v 代表vertical
el: createDefaultScrollbar('h', interactive, this.options.scrollbars, this.options.myStyle)   //h 代表horizontal  

  1662行加入了一个参数myStyle

function createDefaultScrollbar (direction, interactive, type, myStyle)

  1668行加入了这段代码

//    自定义样式
        if(myStyle){ //传入的是一个对象
            var cssString = indicator.style.cssText;
            var newCssString = '';
            var arr = cssString.split(';');
            var obj ={};
            for    (var i=0; i<arr.length; i++){        //生成默认样式的对象形式
                var tempArr = arr[i].split(':');
                obj[tempArr[0]]=tempArr[1];
            }
            /*如果有新的属性替换原有属性,如果没有添加,默认使用原来的
            * */
            for(var k in obj ){
                for(var j in myStyle){
                    if(j==k){
                        obj[k]=myStyle[j];
                    }else{
                        obj[j]=myStyle[j];
                    }
                }
            };
            for(var k in obj){
                newCssString += k + ':' +obj[k] +'\;' ;
            }
            indicator.style.cssText = newCssString;
        }

  然后在公用组件的js加入如下代码

/*
 * 初始化滚动条
 * 需要依赖iscroll.js
 * @param
 * viewbox 滚动的部分外层的窗口  使用querySelector就可以
 * fadeScrollbars 是否需要显示/隐藏滚动条 true/false
 * myStyle  用于自定义样式,如果自定义了样式会覆盖默认样式 ,否则使用默认样式 数据类型对象->{'background-color':'red'}
 *
 * */
//绘制滚动条
function scrollInit(viewbox,fadeScrollbars,myStyle){
    function loaded (viewbox,fadeScrollbars,myStyle) {
        var   myScroll = new IScroll(viewbox, {
            scrollbars: true,
            mouseWheel: true,
            interactiveScrollbars: true,
            shrinkScrollbars: 'scale',
            fadeScrollbars: fadeScrollbars,  //不激活状态下是否隐藏滚动条
            myStyle:myStyle
        });
    }
    document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
    loaded(viewbox,fadeScrollbars,myStyle);

}

  然后在列表数据渲染后再调用scrollInit方法就可以了。

  但是同样到这里还是无法解决滚动条在iframe边缘的问题,但是这次的表现是在iframe上拖动滚动条可以移动,在menu区域拖动没有办法移动。

  做到这里我放弃了这个插件,为什么?因为项目要兼容到ie8,一不小心看到了一个transfrom translate属性在控制滚动条的位置,呵呵,以后一定好先看好兼容性。

  查看css的兼容性最好的网站 CANIUSE.COM

 第二个插件jQuery.nicescroll

  看到这个插件的滚动条的位置使用position控制,我就放心了

  nicescroll支持设置css样式,所以对于我的需求只要满足在iframe边缘不存在影响就好了

  于是对源码做出如下改动

  在1760行绑定事件的地方,加入如下代码即可

if(parent.document){
              self.bind((cap.hasmousecapture) ? self.win : parent.document, "mouseup", self.onmouseup);
              self.bind(parent.document, "mousemove", self.onmousemove);
            };

  同时将工具库里的代码替换成这个

  加一个preViewbox的原因是,滚动条部位的数据会随着页面操作局部刷新,但是绘制代码要跟随执行,防止重复绘制,进行一次判断

  同其他工具一样,都挂到jQuery上。

  

//绘制滚动条
    var preViewbox = null;
    $.scrollInit = function(viewbox,color,hidden){
            if(viewbox == preViewbox){
                $('div[class^=nicescroll]').remove();    //如果以前绘制过将以前的移除
            }
            preViewbox = viewbox;
            $(viewbox).niceScroll({
                cursorcolor: color,//#CC0071 光标颜色
                cursoropacitymax: 1, //改变不透明度非常光标处于活动状态(scrollabar“可见”状态),范围从1到0
                touchbehavior: false, //使光标拖动滚动像在台式电脑触摸设备
                cursorwidth: "5px", //像素光标的宽度
                cursorborder: "0", // 游标边框css定义
                cursorborderradius: "5px",//以像素为光标边界半径
                autohidemode: hidden //是否隐藏滚动条
            });
    }

  然后在想绘制滚动条的部位调用scrollInit就可以了。

  看似简单的一次改动,踩了不少坑,还是自己对iframe嵌套后与原页面的关系没有理清,分享自己的逗逼经验,希望能帮到需要的人。

   菜鸟日记,大神轻喷....

滚动条美化实践(原生js,iscroll,nicescroll)的更多相关文章

  1. jq滚动条美化

    https://github.com/inuyaksa/jquery.nicescroll(插件地址) https://blog.csdn.net/zyy_0725/article/details/8 ...

  2. 原生js实现ajax的文件异步提交功能、图片预览功能.实例

    采用html5使得选择图片改变时,预览框中图片随之改变.input文件选择框美化.原生js完成文件异步提交 效果图: 代码如下,可直接复制并保存为html文件打开查看效果 <html> & ...

  3. 原生JS获取元素宽高实践详解

    开篇的话 任何不是亲身实践中求得的知识,都不是属于你的.任何求得的知识不去时常温习运用,也不是属于你的. 记录由来 在做个上拉广告功能中遇到了一个"理所当然"觉得对的用法,慢慢才排 ...

  4. 原生js实现滚动条

    var SimulateScroll = (function(){ var oParent = document.getElementById('wrap-scroll-bar'), oBox = d ...

  5. 原生js和jquey获取窗口宽高,滚动条,鼠标位置总结

    JQuery获取浏览器窗口的可视区域高度和宽度,滚动条高度   alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height( ...

  6. 原生JS 和 JQ 获取滚动条的高度,以及距离顶部的高度

    JQ:相对比较简便 获取浏览器显示区域(可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 : $(window).width(); 获取页面的文档高度 ...

  7. 原生js实现随着滚动条滚动,导航会自动切换的效果

    最近学习前端,把前面用原生js写的一段有关tab切换效果的代码贴上,实现的效果比较简陋,请大家见谅 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...

  8. 记一次数据、逻辑、视图分离的原生JS项目实践

    一切的开始源于这篇文章:一句话理解Vue核心内容. 在文章中,作者给出了这样一个思考: 假设现在有一个这样的需求,有一张图片,在被点击时,可以记录下被点击的次数. 这看起来很简单吧, 按照上面提到到开 ...

  9. 原生JS实现瀑布流

    浏览网页的时候经常会遇到瀑布流布局的网站.也许有些读者不了解瀑布流.瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数 ...

随机推荐

  1. iOS点击状态栏回到顶部底层实现原理

    在iOS开发中,苹果其实已经帮你实现了点击状态栏回到顶部这个功能,但我们在开发中会遇到点击不能回到顶部.其实这都和 ScrollView中的一个属性scrollsToTop有关,我们先看看苹果关于这个 ...

  2. OLE DB Command transformation 用法

    OLE DB Command transformation component 能够引用参数,逐行调用sqlcommand,This transformation is typically used ...

  3. 深入理解脚本化CSS系列第五篇——动态样式

    前面的话 很多时候,DOM操作比较简单明了,因此用javascript生成那些通常原本是HTML代码生成的内容并不麻烦.但由于浏览器充斥着隐藏的陷阱和不兼容问题,处理DOM中的某些部分时要复杂一些,比 ...

  4. 应用程序框架实战二十二 : DDD分层架构之仓储(层超类型基础篇)

    前一篇介绍了仓储的基本概念,并谈了我对仓储的一些认识,本文将实现仓储的基本功能. 仓储代表聚合在内存中的集合,所以仓储的接口需要模拟得像一个集合.仓储中有很多操作都是可以通用的,可以把这部分操作抽取到 ...

  5. codefordream 关于js中级训练

    中级训练接着就紧锣密鼓的开始了. 首先是关于变量,变量的作用是给一个数据值标注名称. 注:JavaScript中变量名,函数名,参数名的命名规范:至少由字母,下划线,美元符号,数字其中的一种组成,但不 ...

  6. 用JQuery Ajax 与一般处理程序 请求数据无刷新,以及如何调试错误

    通过 ajax() 与 一般处理程序,请求数据库数据,实现界面无刷新. Jquery ajax 请求参数详细说明 http://www.w3school.com.cn/jquery/ajax_ajax ...

  7. 微软消息分析器(Microsoft Message Analyzer )更新至1.2版-2015-1-20

    就在刚才,收到了微软Connect的邮件推送,大名鼎鼎的微软消息分析器更新至1.2版,并且有公众下载链接,大家可以在这里进行下载. 这里简单摘录一下博客里面提到的新版所增加的功能与功能的改进方面. G ...

  8. Groovy学习--基本语法了解

    x项目用到gradle,学习gradle之前准备先过一遍Groovy的语法.这里参考:Groovy入门. 该博客没有系统的讲解Groovy的语法和原理,仅仅只是罗列了使用Groovy的常规方法.我照着 ...

  9. Buff系统设计

    我就随便一写,你也就随便一看吧.   什么是BUFF?   或许直接回答这个问题,那么你收获到的答案将是五花八门的.这个问题暂时放下不谈,我们可以去看其他的游戏应该是怎么设计的. 我经常玩的游戏里边B ...

  10. ASP.Net MVC Action重定向跳出Controller和Area

    1.重定向方法简介 [HttpPost] public ActionResult StudentList( string StudName, string studName, DateTime Bir ...