代码改变世界

山寨iphone缓动滚动条

2011-04-26 00:00  Feather  阅读(582)  评论(1)    收藏  举报

第一句话还是,用IE6的退下,IE7/8勉强可以留下,强烈推荐使用Chrome,FF,Opera,IE9,Safari浏览。

使用方法有点特别,把鼠标移动到滚动栏,不用点击,直接移动,到达目标位置移出滚动栏,如果页面仍然跟随鼠标移动,点击一下可以释放。

至于为什么,下面会解释,可以直接在本页查看,或者点击这里看Demo.

要实现这个效果,只需要可以在自己网页底部插入这段js:

http://www.vinqon.com/codeblog/demo/scroll-min.js

未压缩的源码: http://www.vinqon.com/codeblog/demo/scroll.js (写烂了)

 

如果只是想看看效果,可以随便打开一个网页,在地址栏粘贴一下代码:

javascript:(function(){var a=document.createElement('script');a.src='http://www.vinqon.com/codeblog/demo/scroll-min.js';document.getElementsByTagName('head')[0].appendChild(a)})();

 

实现过程

仿iphone滚动条的想法我很早就有,但为什么要做一个浏览器本身就自带的部件呢?

主要还是受现在很多网站和产品的启发,如果滚动条可以实现缓动,用户体验会有一定的提升。其实我们已经有很多这样的例子了:iphone的UI,Twitter的右栏,维生数工作室网站的部分正文。我也曾经想过直接利用原生滚动条能否也实现缓动,结但是一直想不到比较好的方案。而且其实完全自制一个滚动条难度反而会更低。

其实实现原理很简单,首先把窗口的滚动条隐藏,建两个元素,都使用fixed定位方式定位在右侧,一个是滚动栏,一个是滚动条,设置滚动条可拖动,然后根据拖动位置缓动页面到目标位置。

最蛋疼的问题是,各个浏览器获取窗口,文档,鼠标,元素尺寸和位置的方法各不相同。而且很多具体实现的细节也不一致。

具体各项细节稍后再总结一下。下面我先记录一下目前的一些问题,(划掉的基本解决):

  1. 代码需要优化,目前的代码很杂乱,所以也没有贴出来。最近写代码都没有使用框架,效率低了,但是对很多方法属性兼容办法的记忆加深了。
  2. 定位需要更精确,目前的定位虽然满足使用,但是很明显定位有误差,特别是在顶部和底部的时候可以看出来。
  3. 缓动公式,现在使用的缓动公式很蛋疼,只能无限接近目标位置,不能到达,而且有时会卡住一个未知,因为它没有达到目标就会不停尝试无限接近。
  4. 滚动条的长度应该根据页面长度缩放,现在的滚动条长度是固定的,所以,用户无法直观了解到这个页面的大概长度。
  5. 加入滚轮事件,隐藏滚动条之后,Chrome竟然不能用滚轮滚动页面了,但是Opera和其他一些浏览器可以支持。幸好这些浏览器貌似都支持滚轮事件,可以使用代码来实现,最好实现滚轮页面缓动。
  6. 操作方式。目前的Demo跟常规滚动条不同,这个上面也说了,不需要点击,只要移入滚动条,然后在滚动栏内滑动,页面会跟随滑动。为什么要怎样呢?其实我一开始是实现了常规操作方式的,但是发现问题很多:如果滚动栏使用span元素,移动的时候,略过的高度的文本都会被选中;如果使用div元素,移动的时候有时会在鼠标旁边出现一个禁止标识,释放鼠标后有的“叮”一声。随后我又尝试很多元素,和很多操作方式分别在不同浏览器上操作,总结其使用体验还是觉得目前的方案最好,而且就算用户不知道操作方式,直接拖动也可以滚动页面。
  7. 兼容性。上面都提到一些小兼容性问题,但是一个比较大的问题是如何兼容可恶的IE家族。IE7和IE8其实都不是大问题,只是换换属性方法而已。IE6问题比较严重,而且这个自制滚动条很可能把产生一些副作用。

目前想到的就是上面这些问题,还是满多问题的。

 

3月29日更新

今晚我优化了一下这东西,基本解决了上面被划掉的问题。

主要一个是定位问题:我用全部浏览器尝试了一遍,把它们的获取到的尺寸全部记录下来,分析,笔记如下:

可视窗口尺寸

1. 标准方式。Chrome,FF,IE9 可以使用这两个属性获取: window.innerWidth   window.innerHeight ,它们返回的数值包括滚动条的17px在内,就是说无论是否有滚动条出现,这个尺寸不会改变。

2. IE家族方式。IE7,IE8和IE9(原谅我直接忽略掉IE6)可以用以下两个属性获取可视窗口宽度和高度:

document.getElementsByTagName("html")[0].offsetWidth

document.getElementsByTagName("html")[0].offsetHeight

IE8使用这个方式可以获取与标准方式同样的尺寸,但IE7比较有问题,IE7中的结果不包括17px的滚动条,并且还不包括四周2px的边框(或者边距?),所以如果出现滚动条,它使用IE方式获取的尺寸比标准少21px。IE9很给力,为了保证与旧IE兼容和迎合标准,上面两种方式都可以使用,而且得到的尺寸是一致的,就是上面说的那样。

 

文档尺寸

获取文档尺寸一般都是用一个方式: document.body.offsetHeight和 document.body.offsetWidth,但是,在不同浏览器中返回的具体数值还是有不同。

1.Chrome,FF,IE9获取的数值完全一致,但值得注意的是,这个数值并不是完全等于网页尺寸,因为body元素默认四边都有8px的margin,如果不重置body的margin,宽高两边各加上16px才是真实的尺寸。

2. IE7,8除了margin,貌似还有2px边框,并且无法用css消除,这部分需要待证实,但是四边各少了2px是确定的。IE7很不靠谱,IE7中body的margin默认值与众不同,上下分别是15px,左右为10px

 

鼠标定位

 略

 

 

参考资料

Javascript关于浏览器之间scrollHeight offsetHeight

JS获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度