移動端效果之CellSwiper


寫在前面

接着之前的移動端效果講解,剛好項目中需要使用到這一效果,去餓了么的組件庫看了一下效果,發現效果和微信端的cellSwiper還是有點差別的,由於項目中又是使用的React,之前使用的React所有組件都是自己一個字母一個字母碼起來的(想來也是辛酸),所以結合之前的swiper,道理類似,實現了類似微信端的抽拉效果。

cellSwiper

代碼看這里:github

移動端效果之Swiper

移動端效果之Picker

移動端效果之IndexList

1. 核心解析

1.1 HTML結構

<div class="c-cell-swiper" id="wrapper">
    <div class="cell-content" id="content">
        <div class="your-code">
          	<img class="icon" src="./images/t.jpg"></img>
            <div class="left">
              	<span>萌萌的卡洛奇</span>
              	<p class="sub">我這個月要來看你啦</p>
            </div>
          	<div class="right">now</div>
      </div>
  	</div>
  	<div class="cell-btn-group" id="btnGroup">
    	<div class="cell-btn">標為未讀</div>
    	<div class="cell-btn">刪除</div>
  	</div>
</div>

代碼中類名為your-code的地方是你自己要加的代碼。

做一個效果之前,我們先需要分析一下我們應該怎么做,這樣才能有的放矢。比如這個效果,由於采用的是覆蓋式抽拉,因此,需要兩個層,上面一個層負責滑動,下面一個層固定,當上面的層滑動完成之后,下面的自然就顯示出來了。

因此有兩個點:

  • 上層和下層的層都要絕對定位,這樣才好區別層級(最開始我試的是上面的層不需要決定定位,發現移到項目中的時候,下面的層顯示不出來,因為最開始設置了z-index:-1。但一般的頁面來說,body其實是有一個層級的,因此就會覆蓋下面的層,導致顯示不出來)
  • 既然都采用絕對定位,那么上面的層級的高度就需要計算

1.2 代碼分析

定位好層級之后,下面的按鈕層就可以基本不用管了,主要的操作還是滑動。滑動可以借鑒之前的swiper代碼,這里不作贅述。

1.2.1 計算高度和按鈕組的寬度

var el = document.querySelector('#content');
var btn = document.querySelector('#btnGroup');
var wrapper = document.querySelector('#wrapper');

function getBtnGroupWidth() {
  	// 按鈕組的寬度,滑動的最大距離
    btnGroupWidth = btn.getBoundingClientRect().width;
    wrapperHeight = el.getBoundingClientRect().height;
  	// 設置最上層容器的高度
    wrapper.style.height = wrapperHeight + 'px';
  	// 設置子容器高度
    el.children[0].style.height = wrapperHeight + 'px';
  	// 設置按鈕組的line-height,保證按鈕組文字居中
    btn.style.lineHeight = wrapperHeight + 'px';
}

1.2.2 滑動

// 滑動中 ontouchmove

// ...
// 這里計算的是上層滑動的距離范圍
// 滑動最遠不能超過按鈕組寬度
// 滑動最小距離就是不滑動,也就是0
offsetLeft = Math.min(Math.max(-btnGroupWidth, offsetLeft), 0);
translate(el, offsetLeft);
// ...

// 滑動結束 ontouchend

// ...
// 如果是tap, 直接關閉
if (dragDuration < 300) {
    var fireTap = Math.abs(offsetLeft) < 5 && Math.abs(offsetTop < 5);
    if (isNaN(offsetLeft) || isNaN(offsetTop)) {
      	fireTap = true;
    }
    if (fireTap) {
        translate(el, 0, 150);
        opened = false;
        swiping = false;
        return;
    }
}

var distanceX = Math.abs(offsetLeft);

// 如果向左滑動超過了按鈕組的40%,辣么在松手的一刻自動滑開
// 反之如果向右滑動超過了按鈕組的40%就關閉
if (distanceX > btnGroupWidth * 0.4 && offsetLeft < 0) {
    translate(el, -btnGroupWidth, 150);
    opened = true;
} else {
    translate(el, 0, 150);
    opened = false;
}
// ...

2. 總結

整個流程來說相當於swiper還是相當簡單的,可以說其實就是一個swiper的簡化版本。

重點在於拿到一個效果之后如何分析,只有有清晰的分析思路才能針對這個分析來給出合理的解決方案。這里僅僅記錄自己做這個效果的歷程,拿出來共享,希望對大家有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM