〇、需求
想要实现这种效果
一、问题
在单独一个h5页面中,不调用第三方插件,用最简单代码实现该效果
二、解决
最终发现了两种解决方案,先说一下两个方案的共同前提:
- ① touch 相关事件,判断滑动方向:
this.startX - this.endX > 0
- ② 标志元素进入可见区域:
marker.getBoundingClientRect().right < window.innerWidth
<div class="case-cards" @touchstart="touchStart" @touchend="touchEnd">
<div class="case-card" v-for="item in caseList.slice(0, 2)" :key="item.id">
...
</div>
<div class="case-card case-card-more">
<div class="case-cover">
<img :src="caseList[2].cover || './images/share.png'" :alt="caseList[2].caseTit">
<span class="case-more">
<i class="iconfont"></i>
<p>更多案例</p>
</span>
...
</div>
</div>
</div>
touchStart(e) {
this.startX = e.touches[0].clientX;
},
touchEnd(e) {
this.endX = e.changedTouches[0].clientX;
if (this.startX - this.endX > 0) {
// const scroller = document.getElementsByClassName('case-cards')[0]
const scrollerWrapper = document.getElementsByClassName('case-cards-wrapper')[0]
const marker = document.getElementsByClassName('case-more')[0]
if (marker.getBoundingClientRect().right < window.innerWidth) {
scrollerWrapper.scrollTo({ left: 90, behavior: 'smooth'})
// marker.scrollIntoView({block: "nearest", inline: "end", behavior: "smooth"})
}
console.log(window.innerWidth, marker.getBoundingClientRect().right)
}
},
1.方案一
Element 的scrollTo() 方法可以使界面滚动到给定元素的指定坐标位置。
Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
核心代码:
if (marker.getBoundingClientRect().right < window.innerWidth) {
scrollerWrapper.scrollTo({ left: 90, behavior: 'smooth'})
}
需要注意的是,touch事件绑定在 滑动元素,而 scrollTo 由 该元素 的 父容器 执行!!
2.方案二
Element.scrollIntoView() —— 让当前的元素滚动到浏览器窗口的可视区域内
- 默认参数为true:调用该函数,页面发生滚动,使 element 的顶部与视图(容器)顶部对齐;
- 参数为false:使 element 的底部与视图(容器)底部对齐;
我这边需要横向滚动的刚好是三个 card 的 list ,将可见目标设为:
因此使用了 options (具体参数配置参考文档):
const marker = document.getElementsByClassName('case-more')[0]
marker.scrollIntoView({block: "nearest", inline: "end", behavior: "smooth"})
由于 scrollIntoView 的 options 不支持 ios 系浏览器,因此放弃,改用方案一
拓展阅读: