我司最近在作一个H5,有一个模拟微信对话框的需求,具体需求以下。git
示例: 请看第二屏github
局部滚动效果,以上想法(设置父元素高度而且 overflow:hidden)在PC端能够正常滑动,但 在移动端失效。
这种写法,单独写没有问题,可是IOS端出现卡顿现象,能够添加 -webkit-overflow-scrolling:touch; 解决。web
可是,我司的H5页面使用的swiper制做,大概是这个有一些影响,用户滑动屏幕首先触发了swiper的事件。(仅作设想,后续作进一步实践)微信
因而在网上查了几番,有如下几种解决方法app
改变元素的transform值,须要判断用户的滑动方向。
判断滑动方向时,先了解两个事件ide
了解了这两个事件,咱们能够在用户触发touchstart事件时,记录手指位置,在touchmove记录获取手指最后停留的位置
判断 最后停留位置 - 初始位置= pageY- startY = 即用户滑动方向 oop
(pageY-startY)为正数时,说明用户向下滑动;为负数时,说明用户向上滑动。测试
$(".message-wrapper").on("touchstart", function (e) { startY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; }) $(".message-wrapper").on("touchmove", function (e) { pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; })
网上有不少关于iscroll的资料,可是我查了一下官方的github,最近的更新在5年前,果断不敢用~this
查了一番,swiper里的 swiper-scrollbar能够完美的实现这一功能,单独写这一功能,在真机测试没有问题。而后移入到咱们的项目中。出现如下几个问题spa
出现这个问题的缘由,是因为我司的H5项目也是由swiper制做,这意味着每一屏就至关于一个slide,当添加用swiper完成的局部滚动时,会形成后面父元素的slide元素不显示。
这涉及到多个swiper嵌套使用的问题,具体修改以下:
当页面存在多个swiper,初始化时,尽可能避免使用同样的类名,如 .swiper-container,每一个swiper有它单独的类名
<div class="swiper-container main-swiper"> //父元素swiper <div class="swiper-wrapper"> <div class="swiper-slide slide1"></div> <div class="swiper-slide slide2"> <div class="swiper-container message-warp"> //子元素swiper <div class="swiper-wrapper message-wrapper"> <div class="swiper-slide message-slide"></div> </div> </div> </div> <div class="swiper-slide slide3"></div> </div> </div> //-------------------------------------------------------------swiper初始化
若是类名分开,父元素后续slide元素依然没法显示
将子元素的初始化,写在父元素初始化以前,加载时,优先初始化子元素swiper
//初始化子swiper var scrollSwiper = new Swiper('.message-warp', { observer: true, observeParents: false, scrollbar: '.swiper-scrollbar', direction: 'vertical', slidesPerView: 'auto', mousewheelControl: true, freeMode: true, }) var swiper = new Swiper('.main-swiper', { direction: 'vertical', touchRatio: 0.5, loop: false, on: { init: function () { swiperAnimate(this); }, slideChangeTransitionEnd: function (e) { swiperAnimate(this) } } });
swiper运行时,会先给元素添加visiblity:hidden;使元素隐藏,只给当前页的visiblity设置为visible;而swiper中,改元素显示状态的依据就是swiper-slide-active;
swiper默认给当前的slide添加swiper-slide-active类名。当页面中存在swiper嵌套时,父元素的当前slide会添加该类名,子元素的当前slide也会添加该类名。
这样当用户滑出父元素的当前slide时父元素的swiper-slide-active被移除,而子元素的swiper-slide-active类名并无移除,形成swiper混乱,因此父元素后续slide的元素会没法显示
解决办法
个人作法是在父元素切换slide后,判断页面中swiper-slide-active的个数,若是存在一个以上,则说明子元素的类名没有移除。
手动将子元素的swiper-slide-active类名移除便可。
暂时尚未想到更好的方法,若是你有更好的方法,欢迎一块儿讨论。
if ($(".swiper-slide-active").length == 2) { $(".message-slide").removeClass("swiper-slide-active") }