谨慎设置iScroll4的useTransform属性,他会导致scrollToElement方法表现异常

问题描述:

  在创建iScroll实例的时候设置useTransform属性值为false,结果后面在使用scrollToElement方法滑动页面到指定位置时,除非滑动区域初始滑动距离为0,否则使用scrollToElement滑动时总会出现一定偏差,初始滑动距离越大,偏差越大。

原因分析:

  1、找到scrollToElement方法的定义: 

    scrollToElement: function (el, time) {
            var that = this, pos;
            el = el.nodeType ? el : that.scroller.querySelector(el);
            if (!el) return;

            pos = that._offset(el);
            pos.left += that.wrapperOffsetLeft;
            pos.top += that.wrapperOffsetTop;

            pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
            pos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
            time = time === undefined ? m.max(m.abs(pos.left) * 2, m.abs(pos.top) * 2) : time;

            that.scrollTo(pos.left, pos.top, time);
        }

  调试可发现,出现问题时以上代码中that._offset(el)方法放回的数据有问题(pos.top值偏小);

  2、找到offset(el)方法定义

    _offset: function (el) {
            var left = -el.offsetLeft,
                top = -el.offsetTop;

            while (el = el.offsetParent) {
                left -= el.offsetLeft;
                top -= el.offsetTop;
            }

            if (el != this.wrapper) {
                left *= this.scale;
                top *= this.scale;
            }

            return {left: left, top: top};
        }

  问题就出在红色标记部分了,调试可发现top值多减去了滑动区域的offsetTop,这又是为什么呢?

  看一下offsetParent是什么意思:

offsetParent属性返回一个对象的引用,这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的容器元素。 如果这个容器元素未进行CSS定位, 则offsetParent属性的取值为根元素(在标准兼容模式下为html元素;在怪异呈现模式下为body元素)的引用。 当容器元素的style.display 被设置为 "none"时(译注:IE和Opera除外),offsetParent属性 返回 null。

  简单的说就是获取最近有设置position属性的父元素,但我们一般都不会给滑动区域设置position属性的,可通过调试发现滑动区域确实有设置position属性,这是为啥?于是想到了iScroll的构造函数。

  在iScroll4的构造函数中有一下代码,若useTransform为false,则会给滑动块(scroller)添加css属性position:absolute;

if (that.options.useTransform) that.scroller.style[transform] = ‘translate(‘ + that.x + ‘px,‘ + that.y + ‘px)‘ + translateZ;
else that.scroller.style.cssText += ‘;position:absolute;top:‘ + that.y + ‘px;left:‘ + that.x + ‘px‘;

  至此终于真相大白!

  总结下:在创建iScroll4实例时若设置seTransform为false,则iScroll4会给可滑动区域设置position:absolute,导致在运行scrollToElement方法过程中调用_offset方法计算滑动距离时会把滑动区域的offsetTop值也计算进去,最终导致滑动距离小于预期。

解决方案:

  修改_offset定义,使其不计算滑动区域offset:

    _offset: function (el) {
            var left = -el.offsetLeft,
                top = -el.offsetTop;

            while (el = el.offsetParent) {
                if (el == this.scroller) continue;//若为滑动块,则跳过
                left -= el.offsetLeft;
                top -= el.offsetTop;
            }

            if (el != this.wrapper) {
                left *= this.scale;
                top *= this.scale;
            }

            return {left: left, top: top};
        }
时间: 2024-08-05 08:58:52

谨慎设置iScroll4的useTransform属性,他会导致scrollToElement方法表现异常的相关文章

Android:Adapter中设置多种type的item的LayoutParams导致的convertView复用异常的问题

http://stackoverflow.com/questions/12018997/why-does-getview-return-wrong-convertview-objects-on-separatedlistadapter#comment35496677_12288051 The recycle bin technically stores the convert views based on the type that was initially read from getItem

iOS UIButton同时设置title和image属性

在iOS开发中,使用UIButton设置title和image,达到tabBarItem的效果,即title在下,image在上: 目前,我发现有两种比较好的方法: 方法一,使用UIEdgeInsets UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setFrame:CGRectMake(100, 100, 60, 60)]; [button setBackgroundColor:[UIColor

agruments应用——求出函数参数的总合&amp;&amp;css函数——设置/读取对象的属性&amp;&amp;当前输入框高亮显

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

C#中 选项卡(Tabcontrol)动态添加TabPage(获取或设置当前选项卡及其属性)

新建一个WinForm程序,拖一个TabControl(在tabPages属性里面将默认的两个TabPage删除)和三个Button(增加.删除.修改) public partial class Form1 : Form { private int index = 0; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //this.tabControl1

jQuery - 设置获取内容和属性

获取选中select :$("#id option:selected").val(); 自定义radio:    $("input[name=sex][value="+data.sex+"]").attr("checked",true); 获取radio:           $("input[name='sex']:checked").val() 设置input不能编辑:$("#cashNum&

设置UINavigationController标题的属性

self.title = @"产品详情"; [self.navigationController.navigationBar setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [UIColor redColor], NSForegroundColorAttributeName, [UIFont systemFontOfSize:20.f], NSFontAttributeName, nil]]; 可以

html基础 设置img的align属性,left,right 实现图文混排的效果

镇场诗: 清心感悟智慧语,不着世间名与利.学水处下纳百川,舍尽贡高我慢意. 学有小成返哺根,愿铸一良心博客.诚心于此写经验,愿见文者得启发.------------------------------------------ ex1: code: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; chars

IE下设置unselectable与onselectstart属性的bug,Firefox与Chrome下的解决方案

在IE下给DIV设置unselectable与onselectstart属性,可以让div的内容不能选中,这个功能在很多情况下,非常有用,但是他的bug太明显, 直接使用一个DIV是可以的,比如: [html] view plaincopy <div unselectable="on" onselectstart="return false;">不能选中的内容</div> 但是假如在这个DIV前面在出现一个普通的DIV,那就有问题了,比如:

jquery中使用css,offset和position设置top和left属性

有一个dom元素,它的position属性值为absolute,要通过jquery设置它的位置. 我们可以通过三种方法设置该元素的top和left值,设置这两个属性的值时,元素的position属性必须为absolute或relative. 第一种:使用jQuery对象的css方法,使用该方法可以直接把对象的位置设定到指定的地方,指定哪个位置就是哪个位置. 第二种:使用jQuery对象的offset方法,使用该方法时要注意,offset方法的作用是获取或设置匹配元素在当前视口的相对偏移.这句话粗