8***@qq.com
8***@qq.com
  • 发布:2017-06-26 19:05
  • 更新:2018-11-13 11:41
  • 阅读:5205

导航栏透明渐变效果跟mui-scroll-wrapper冲突了

分类:MUI

<div id="pullrefresh" class="mui-scroll-wrapper">
<div class="mui-scroll">
</div>
</div>

安卓手机没有bug,但是IOS的不能显示渐变效果,看见一位前辈说scrollY冲突了,重写一下Transparent,其中的handleScroll。原因确实是这个,不过还不清楚如何解决,望各位大神不吝指教!

2017-06-26 19:05 负责人:无 分享
已邀请:

最佳回复

Trust

Trust - 少说废话

参考附件中的示例处理一下,后续优化此组件。

下载示例后,将其复制到 hello mui 示例工程的根目录下,即可预览效果。

  • 路人甲LURENJIA

    这个方法在没有图片轮播的时候可行,但是如果页面有图片轮播,一轮播导航栏就会消失了。有没有什么解决方法吗?

    2020-07-07 18:53

  • 1***@qq.com

    回复 路人甲LURENJIA: 在mui.js中的Transparent.prototype.handleScroll函数中进行判断,排除mui-slider即可

    2020-09-22 10:29

  • 1***@qq.com

    Transparent.prototype.handleScroll = function(e) {

    var y = window.scrollY;

    if (!this.isNativeScroll && e && e.detail) {

    y = -e.detail.y;

    }


        //由于图片轮播导致handleScroll事件触发,获取到的e.detail.y为0,此处进行过滤  
    if( e && e.detail && e.detail.element['_prevClass']=='mui-slider'){
    return
    }

    var opacity = (y - this.options.top) / this.options.offset + this._A;
    opacity = Math.min(Math.max(this._A, opacity), 1);
    this._style.backgroundColor = 'rgba(' + this._R + ',' + this._G + ',' + this._B + ',' + opacity + ')';
    if (opacity > this._A) {
    this.element.classList.add(CLASS_ACTIVE);
    } else {
    this.element.classList.remove(CLASS_ACTIVE);
    }
    if (this.lastOpacity !== opacity) {
    $.trigger(this.element, 'alpha', {
    alpha: opacity
    });
    this.lastOpacity = opacity;
    }
    };

    2020-09-22 10:30

8***@qq.com

8***@qq.com (作者)

有没有大神解决了的

MUI_Charles

MUI_Charles

刚好碰到这个问题,分享一下解决思路,对解决其他一些监听滚动的问题也有帮助。
结合源码图消化效果更佳。P.S. Line[8056-8058]是修改添加后的源码

注意到末尾Line:8109对含有mui-bar-transparent这个class的元素初始化ready后调用了一次

mui('.mui-bar-transparent').transparent();

组件的4个可选参数应该都比较好理解,上面的调用没有传参,根据Line:8019的逻辑,导航栏的透明度改变是根据默认window(或者说body)的滚动来计算的,对于hellomui中的nav-transparent.html这样的简单页面是有效的。

但是想要指定根据某个容器的滚动来计算的话,在不修改源码的情况下,局限性还是比较大的,下面指出源码的3个关键点以及大部分不生效的原因。

1.Line:8023--实例对象上挂了一个属性isNativeScroll,默认为false,当监听容器为window或者非mScroll容器时,值为true。从initEvent可以看出,这个值是用来判断监听滚动的容器是否需要添加touchmove事件的监听,mScroll自带touchmove监听,无需重复添加。值得注意的是,在初始化transparent组件之前,如果这个容器之前已经初始过了,需要调用mui('.xxx').transparent().destroy()销毁原实例,以免重复绑定事件,导致效果无常;

2.Line:8026--限制了指定的容器必须是mScroll组件的容器,必须含class名mui-scroll-wrapper。

3.Line:8054--仅当滚动事件e(event)有detail属性时,滚动距离y才会从e.detail.y里取值。这两点涉及到了mScroll组件的实现原理,简而言之,是使用两层容器利用绝对定位和transform:translate3D(x,y,z)动画,加上touchmove以及自定事件customEvent来实现滚动效果的。默认事件流对象是没有detail这个属性的,从文档中可以了解到mui大多数组件的回调、监听事件都是有detail这样一个用于回调传值的形参。那么滚动距离y(正值)是从mScroll组件滚动时触发的自定事件里拿到的e.detail.y(负值)取反用来计算透明度,如果不满足这两点,滚动距离y保持缺省值window.scrollY(Line:8053)。

综上三点,上述局限性就在于只能指定mScroll容器作为scrollby参数值,一旦不满足2、3点中的条件,比如下拉刷新上拉加载、iScroll一类组件,尽管传入了指定的容器dom,在handleScroll时,y还是保持window.scrollY,滚动容器与window(body)滚动大多数情况下是老死不相往来,滚动距离y取值自然一直取window.scrollY的初始值0,计算出来的opacity则一直为0,也就是没有效果的原因。

相对应地,在Line[8056-8058]添加了y的取值点,

y = this.scrollByElem.scrollTop;

从传入的scrollby即scrollByElem容器上取scrollTop值,不过,这并非通用的解决办法,还得按需灵活处理,关键点在于要从scrollby传入的容器dom上拿到滚动距离,建议按照实际情况实际处理。这应该也是上述局限性存在的原因,因为很难找到满足所有需求场景的取值逻辑,如果统一使用mScroll组件,就比较好处理。

最后需要注意一点的是,参数duration不要设置过大,因为duration作用于实例上的节流函数_bufferFn,设定了节流周期,按照1秒24帧算下来1000/24≈42,如果duration>>42,滚动触发的透明度变化的“动画”将小于24帧,界面可能产生明显的锯齿般的卡顿挫感,同样地,建议按照实际情况实际处理。

该问题目前已经被锁定, 无法添加新回复