zoukankan      html  css  js  c++  java
  • 谨慎设置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};
            }
  • 相关阅读:
    java中bean和xml相互转换
    java操作zip文件
    java内置的解压缩工具
    java操作Excel简单入门
    java开发IDEA插件入门
    java中Class.getResourceAsStream()和ClassLoader.getResourceAsStream()的区别
    java中文转拼音
    vue父子组件通信
    学会使用box-sizing布局
    webpack-dev-server 导致的 invalid host header
  • 原文地址:https://www.cnblogs.com/dragon-aslan/p/4723769.html
Copyright © 2011-2022 走看看