开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情
移动端需求
时间紧急,有个高优需求,移动端高端的特效,只给两天时间,直接无语。根本无法实现,紧急和大佬讨论一番,大佬直接开始砍需求,告知他的设计虽然巧夺天工,但是移动端上实现起来异常麻烦,而且效果也不会像想象的那么顺其自然。然后,直接将复杂的逻辑简化了,搞成左右滑动即可
然而
然而左右滑动我也没搞过,好兄弟建议我使用swiper,但是那么怎么能行,大家都知道我是cv大师了。不可强攻,只能智取
上代码
首先,先搭建ui,然,思想就是首先有个容器,然后容器宽度是屏幕宽度,内部有个子元素,子元素宽度为有几屏幕就有机屏幕的宽度。然后给个display flex, 里面的子元素flex 1 就能保证每个子元素自己一屏幕了。然后样式就这样。
有几个状态,pageIndex当前是第几页激活。也就是显示第几页,第二个是startX,记录手势开始的x坐标,然后在 touchmove里判断边界情况,就是在最左边就不能往左滑了,最右边就不能往右滑了。怎么区分往左往右呢?判断xd当前坐标,如果大于startX 就是往右滑了,反过来就是往左滑。然后根据左右 或者加减pageindex,根据左右位置,实时的更新元素移动的位移,当前要加上前面页占的距离。松手后,根据移动距离来决定是否翻页,力度自己控制,灵敏一点就少一点距离就翻页,否则就恢复到之前的位置 移动端实现左右移动,要利用手势事件 // touchStart // touchMove // touchEnd
过成中可以给对应的dom增加一个样式,然后突出一下。因为是移动端适配,所以要计算一下宽度
这三个事件打好配合
<script>
document.documentElement.style.fontSize = document.documentElement.clientWidth / 37.5 + 'px'
</script>
<style>
body {
margin: 0;
}
.slide-page {
position: relative;
width: 100%;
height: 120px;
padding: 30px 0px;
overflow: hidden;
}
.scroll-wrapper {
position: absolute;
height: 100px;
display: flex;
width: calc(100% + (100% - 8rem) * 3);
transition: transform .2s ease 0s;
}
.slide-item {
width: calc(100% - 8rem);
transform: scale(0.8);
}
.slide-item .inner {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 10rem;
}
.slide-item:nth-child(1) {
background-color: #09f;
margin-left: 4rem;
}
.slide-item:nth-child(2) {
background-color: #990;
}
.slide-item:nth-child(3) {
background-color: rgb(41, 149, 140);
}
.slide-item:nth-child(4) {
background-color: rgb(126, 31, 31);
margin-right: 4rem;
}
.active {
transform: scale(1);
}
</style>
</head>
<body>
<div class="app">
<div class="slide-page">
<div class="scroll-wrapper">
<div class="slide-item active">
<div class="inner">page1</div>
</div>
<div class="slide-item">
<div class="inner">page2</div>
</div>
<div class="slide-item">
<div class="inner">page3</div>
</div>
<div class="slide-item">
<div class="inner">page4</div>
</div>
</div>
</div>
</div>
</body>
<script>
// touchStart
// touchMove
// touchEnd
const oSlidePage = document.querySelector('.slide-page'),
oScrollWrapper = document.querySelector('.scroll-wrapper'),
oSlideItemList = document.querySelectorAll('.slide-item'),
pageWidth = document.documentElement.clientWidth - document.documentElement.clientWidth / 37.5 * 8
let startX = 0
let pageIndex = 0
let distanceX = 0
let isMove = false
const init = () => {
bindEvent()
}
function bindEvent () {
oScrollWrapper.addEventListener('touchstart', handlerTouchStart)
oScrollWrapper.addEventListener('touchmove', handlerTouchMove)
oScrollWrapper.addEventListener('touchend', handlerTouchEnd)
}
function handlerTouchStart (e) {
startX = e.touches[0].clientX
}
function handlerTouchMove (e) {
const moveX = e.touches[0].clientX
if ((moveX > startX && pageIndex === 0) || (moveX < startX && pageIndex === oSlideItemList.length - 1)) {
return
}
// 实时的位移距离
distanceX = moveX - startX
// setTranslateX(-pageWidth * pageIndex + distanceX)
isMove = true
}
function handlerTouchEnd () {
if (isMove) {
//切换
if (Math.abs(distanceX) >= pageWidth / 4) {
// 往右滑
if (distanceX > 0) {
pageIndex--
} else {
pageIndex++
}
}
setTranslateX(-pageIndex * pageWidth)
oSlideItemList.forEach(item => item.classList.remove('active'))
oSlideItemList[pageIndex].classList.add('active')
startX = 0
distanceX = 0
isMove = false
}
}
function setTranslateX (transX) {
oScrollWrapper.style.transform = `translateX(${transX}px)`
}
init()
</script>