滚动条美化实践(原生js,iscroll,nicescroll)
近期需要改造项目中的滚动条,使原滚动条在三大浏览器下表现相同,分享一下自己的改造经历:
项目中的滚动条分布在网页的各个小窗口中,使用的是-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)的更多相关文章
- jq滚动条美化
https://github.com/inuyaksa/jquery.nicescroll(插件地址) https://blog.csdn.net/zyy_0725/article/details/8 ...
- 原生js实现ajax的文件异步提交功能、图片预览功能.实例
采用html5使得选择图片改变时,预览框中图片随之改变.input文件选择框美化.原生js完成文件异步提交 效果图: 代码如下,可直接复制并保存为html文件打开查看效果 <html> & ...
- 原生JS获取元素宽高实践详解
开篇的话 任何不是亲身实践中求得的知识,都不是属于你的.任何求得的知识不去时常温习运用,也不是属于你的. 记录由来 在做个上拉广告功能中遇到了一个"理所当然"觉得对的用法,慢慢才排 ...
- 原生js实现滚动条
var SimulateScroll = (function(){ var oParent = document.getElementById('wrap-scroll-bar'), oBox = d ...
- 原生js和jquey获取窗口宽高,滚动条,鼠标位置总结
JQuery获取浏览器窗口的可视区域高度和宽度,滚动条高度 alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height( ...
- 原生JS 和 JQ 获取滚动条的高度,以及距离顶部的高度
JQ:相对比较简便 获取浏览器显示区域(可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 : $(window).width(); 获取页面的文档高度 ...
- 原生js实现随着滚动条滚动,导航会自动切换的效果
最近学习前端,把前面用原生js写的一段有关tab切换效果的代码贴上,实现的效果比较简陋,请大家见谅 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...
- 记一次数据、逻辑、视图分离的原生JS项目实践
一切的开始源于这篇文章:一句话理解Vue核心内容. 在文章中,作者给出了这样一个思考: 假设现在有一个这样的需求,有一张图片,在被点击时,可以记录下被点击的次数. 这看起来很简单吧, 按照上面提到到开 ...
- 原生JS实现瀑布流
浏览网页的时候经常会遇到瀑布流布局的网站.也许有些读者不了解瀑布流.瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数 ...
随机推荐
- jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器
jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求,分别是: 1.前置过滤器 jQuery. ajaxPrefilter 2.请求分发器 jQuery. ajaxTran ...
- javascript运动系列第六篇——轨迹和投掷
× 目录 [1]运动轨迹 [2]拖拽轨迹 [3]投掷 前面的话 一般地,不同的运动形式会产生不同的轨迹.但仅凭肉眼去识别运动轨迹,其实并不是很直观.因此,在页面中显示运动轨迹,是一个重要的问题.物体初 ...
- Android 对程序异常崩溃的捕捉
转载博客:http://blog.csdn.net/i_lovefish/article/details/17719081 以下为异常捕捉处理代码: import java.io.BufferedRe ...
- 引用类型-RegExp类型
JavaScript高级程序设计(第三版)笔记-第五章-RegExp类型 定义正则表达式有两种方式 1.用字面量形式定义正则表达式: ver expression = /patterns/flags; ...
- 拨乱反正:DDD 回归具体的业务场景,Domain Model 再再重新设计
首先,把最真挚的情感送与梅西,加油! 写在前面 阅读目录: 重申业务场景 Domain Model 设计 后记 上一篇<设计窘境:来自 Repository 的一丝线索,Domain Model ...
- Java内存模型深度解析:final--转
原文地址:http://www.codeceo.com/article/java-memory-6.html 与前面介绍的锁和Volatile相比较,对final域的读和写更像是普通的变量访问.对于f ...
- iOS homekit使用说明
本文由CocoaChina翻译组成员iBenjamin_Go和浅夏@旧时光翻译自苹果开发文档:HomeKit Developer Guide,敬请勘误. 本文档内容包括 第一部分:简介 第二部分:启用 ...
- ZOJ Problem Set - 1394 Polar Explorer
这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...
- Anliven - 基础知识梳理汇总 - 软件测试
基础知识梳理 - 软件测试 - 概念 基础知识梳理 - 软件测试 - 分类 基础知识梳理 - 软件测试 - 流程 基础知识梳理 - 软件测试 - 用例 基础知识梳理 - 软件测试 - 方法 基础知识梳 ...
- Cesium应用篇:3控件(3)SelectionIndicator& InfoBox
假设这样一个场景,用户在Cesium球上加载了一个GeoJson文件(DataSource),里面是全美国所有州的Geometry信息(Entity),叠加到球面后,你自然会有一种冲动,点击某一个州, ...