1. 程式人生 > >基於jQuery的左滑出現刪除按鈕

基於jQuery的左滑出現刪除按鈕

最近在做專案的時候遇到了個需求,在網頁上實現類似於QQ會話列表那樣子的左滑出現刪除按鈕的效果,於是嘗試著寫了一個,寫出來與大家交流分享,大神勿噴。

基本要求

由於我們是在做一個跨平臺的APP,裡面部分介面其實就是WebView載入的網頁,因此需要使用網頁實現這樣的效果:往左滑動時,顯示刪除按鈕,再往右滑,隱藏刪除按鈕。

成品示例圖

額,先上圖吧。下面分別是在PC瀏覽器裡和在Mobile瀏覽器裡的效果。

PC瀏覽器

這裡寫圖片描述

手機瀏覽器

這裡寫圖片描述

實現思路

為了說明我的實現思路,做了兩個圖來輔助說明。

  1. 首先,請看圖1。在圖中,我們設定每一行的寬度超過瀏覽器的寬度,其超出的部分就是放置按鈕的區域。由於超出了瀏覽器的最大寬度,因此按鈕區域此時是不可見的,只能顯示左側的常規資訊部分。

    圖1 普通狀態
    圖1 普通狀態

  2. 接下來,我們監聽左側常規資訊區域,監聽滑動事件(具體如何監聽先不考慮)。當我們監聽到左滑事件時,我們讓相應行左偏移,讓按鈕顯示出來,同時左側超出的部分被遮擋(請看圖2)。

    圖2 左滑狀態
    這裡寫圖片描述

  3. 當我們右滑時,我們再讓相應行回覆到左偏移為0的時候就行了。

關鍵實現方式

  • 對於左滑和右滑,我們通過設定常規資訊區域的marin-left來實現,當設定margin-left為負值時,實現左滑,當再次設定margin-left為0時,實現右滑。
  • 對於滑動事件監聽,通過監聽滑鼠(手指)按下和擡起來實現,根據兩點的X座標的差值的正負判定是右滑還是左滑。

完整程式碼

需要注意的是,我在測試的時候用的是chrome的普通模式和mobile模擬器模式,發現兩種模式下監聽是不一樣的,因此我寫了兩種監聽,這樣至少有一種會執行。也許有其他更好的適配方法,但不作為此處的重點。當然也歡迎大家賜教。

至於程式碼部分,用了jQuery,其實不用也沒啥問題的,動畫滑動和監聽都可以用純js寫,但是由於這不是這裡的重點,那麼為什麼不用jQuery呢?成功者站在巨人的肩膀上,而且咱也沒有jQuery寫的好 (。・`ω´・)

2015/11/13更新

有位同學提出說程式碼在QQ手機瀏覽器和Opera手機瀏覽器等中沒有滑動效果,找了一下大概是這個帖子http://bbs.mb.qq.com/thread-201794-1-1.html

裡說的原因,於是根據帖子裡的提示以及那位同學的一個大神同學的提示,做了一下修改。主要是在touchmove事件中根據橫縱座標位移來判斷是否阻止預設事件,如下:

// 橫向位移大於縱向位移,阻止縱向滾動
if (Math.abs(delta.x) > Math.abs(delta.y)) {
    event.preventDefault();
}

2016/02/25更新

qq_25558115同學提到:“如果再能給大家提供出只能有一條記錄可以左滑, 倘若滑動其他的記錄,則有左滑記錄的要回到原位”。於是進行了簡單實現。主要思路如下:

// 用一個變數記錄上一次左滑的物件
var lastLeftObj;

// 在左滑發生的時候,判定上一個左滑的物件是否存在,若存在,且不是當前被左滑的物件,則將其右滑
// 同時,記錄新的左滑物件
// 在右滑發生時,將上一個左滑物件清空
if (左滑) {
    pressedObj左滑
    lastLeftObj && lastLeftObj != pressedObj && lastLeftObj右滑
    lastLeftObj = pressedObj; // 記錄上一個左滑的物件
} else if (右滑) {
    pressedObj右滑
    lastLeftObj = null; // 清空上一個左滑的物件
}

2016/09/06更新

根據馬燦發同學提出的bug進行修改:

右滑時進行判斷,僅當要右滑的物件(pressedObj)是上一次左滑的物件(lastLeftObj)時才將物件右滑並清空lastLeftObj。

if (pressedObj == lastLeftObj) {...}

根據girlyougo同學的提議,新增“在除本行外的其他區域點選時均復位當前左滑按鈕”的功能。思路為在滑動結束時,判定pressedObj!=lastLeftObj,即可知點選/滑動的物件為其他物件

// 點選除當前左滑物件之外的任意其他位置
if (lastLeftObj && pressedObj != lastLeftObj) {
    $(lastLeftObj).animate({marginLeft:"0"}, 500); // 右滑
    lastLeftObj = null; // 清空上一個左滑的物件
}

實際上,在添加了上述功能之後,前面提到的bug不存在了。不過此處保留了消除bug的那部分程式碼。

更新後的完整程式碼如下:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>左劃出現刪除按鈕,右滑隱藏</title>
<script type="text/javascript" src="jquery-1.11.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function(e) {
    // 設定每一行的寬度=螢幕寬度+按鈕寬度
    $(".line-scroll-wrapper").width($(".line-wrapper").width() + $(".line-btn-delete").width());
    // 設定常規資訊區域寬度=螢幕寬度
    $(".line-normal-wrapper").width($(".line-wrapper").width());
    // 設定文字部分寬度(為了實現文字過長時在末尾顯示...)
    $(".line-normal-msg").width($(".line-normal-wrapper").width() - 280);

    // 獲取所有行,對每一行設定監聽
    var lines = $(".line-normal-wrapper");
    var len = lines.length; 
    var lastX, lastXForMobile;

    // 用於記錄被按下的物件
    var pressedObj;  // 當前左滑的物件
    var lastLeftObj; // 上一個左滑的物件

    // 用於記錄按下的點
    var start;

    // 網頁在移動端執行時的監聽
    for (var i = 0; i < len; ++i) {
        lines[i].addEventListener('touchstart', function(e){
            lastXForMobile = e.changedTouches[0].pageX;
            pressedObj = this; // 記錄被按下的物件 

            // 記錄開始按下時的點
            var touches = event.touches[0];
            start = { 
                x: touches.pageX, // 橫座標
                y: touches.pageY  // 縱座標
            };
        });

        lines[i].addEventListener('touchmove',function(e){
            // 計算划動過程中x和y的變化量
            var touches = event.touches[0];
            delta = {
                x: touches.pageX - start.x,
                y: touches.pageY - start.y
            };

            // 橫向位移大於縱向位移,阻止縱向滾動
            if (Math.abs(delta.x) > Math.abs(delta.y)) {
                event.preventDefault();
            }
        });

        lines[i].addEventListener('touchend', function(e){
            if (lastLeftObj && pressedObj != lastLeftObj) { // 點選除當前左滑物件之外的任意其他位置
                $(lastLeftObj).animate({marginLeft:"0"}, 500); // 右滑
                lastLeftObj = null; // 清空上一個左滑的物件
            }
            var diffX = e.changedTouches[0].pageX - lastXForMobile;
            if (diffX < -150) {
                $(pressedObj).animate({marginLeft:"-132px"}, 500); // 左滑
                lastLeftObj && lastLeftObj != pressedObj && 
                    $(lastLeftObj).animate({marginLeft:"0"}, 500); // 已經左滑狀態的按鈕右滑
                lastLeftObj = pressedObj; // 記錄上一個左滑的物件
            } else if (diffX > 150) {
              if (pressedObj == lastLeftObj) {
                $(pressedObj).animate({marginLeft:"0"}, 500); // 右滑
                lastLeftObj = null; // 清空上一個左滑的物件
              }
            }
        });
    }

    // 網頁在PC瀏覽器中執行時的監聽
    for (var i = 0; i < len; ++i) {
        $(lines[i]).bind('mousedown', function(e){
            lastX = e.clientX;
            pressedObj = this; // 記錄被按下的物件
        });

        $(lines[i]).bind('mouseup', function(e){
            if (lastLeftObj && pressedObj != lastLeftObj) { // 點選除當前左滑物件之外的任意其他位置
                $(lastLeftObj).animate({marginLeft:"0"}, 500); // 右滑
                lastLeftObj = null; // 清空上一個左滑的物件
            }
            var diffX = e.clientX - lastX;
            if (diffX < -150) {
                $(pressedObj).animate({marginLeft:"-132px"}, 500); // 左滑
                lastLeftObj && lastLeftObj != pressedObj && 
                    $(lastLeftObj).animate({marginLeft:"0"}, 500); // 已經左滑狀態的按鈕右滑
                lastLeftObj = pressedObj; // 記錄上一個左滑的物件
            } else if (diffX > 150) {
              if (pressedObj == lastLeftObj) {
                $(pressedObj).animate({marginLeft:"0"}, 500); // 右滑
                lastLeftObj = null; // 清空上一個左滑的物件
              }
            }
        });
    }
});
</script>
<style type="text/css">
* { margin: 0; padding: 0; }
.line-wrapper { width: 100%; height: 144px; overflow: hidden; font-size: 28px; border-bottom: 1px solid #aaa; }
.line-scroll-wrapper { white-space: nowrap; height: 144px; clear: both; }
.line-btn-delete { float: left; width: 132px; height: 144px; }
.line-btn-delete button { width: 100%; height: 100%; background: red; border: none; font-size: 24px; font-family: 'Microsoft Yahei'; color: #fff; }
.line-normal-wrapper { display: inline-block; line-height: 100px; float: left; padding-top: 10px; padding-bottom: 10px; }
.line-normal-icon-wrapper { float: right; width: 120px; height: 120px; margin-right: 12px; }
.line-normal-icon-wrapper img { width: 120px; height: 120px; }
.line-normal-avatar-wrapper { width: 100px; height: 124px; float: left; margin-left: 12px; }
.line-normal-avatar-wrapper img { width: 92px; height: 92px; border-radius: 60px; }
.line-normal-left-wrapper { float: left; overflow: hidden; }
.line-normal-info-wrapper { float: left; margin-left: 10px; }
.line-normal-user-name { height: 28px; line-height: 28px; color: #4e4e4e; margin-top: 7px; }
.line-normal-msg { height: 28px; line-height: 28px; overflow:hidden; text-overflow:ellipsis; color: #4e4e4e; margin-top: 11px; }
.line-normal-time { height: 28px; line-height: 28px; color: #999; margin-top: 11px; }
</style>
</head>
<body>
<div class="line-wrapper">
  <div class="line-scroll-wrapper">
    <div class="line-normal-wrapper">
      <div class="line-normal-left-wrapper">
        <div class="line-normal-avatar-wrapper"><img src="1.jpg" /></div>
        <div class="line-normal-info-wrapper">
          <div class="line-normal-user-name">蠟筆小新</div>
          <div class="line-normal-msg">在同行的小夥伴中提到了你</div>
          <div class="line-normal-time">1分鐘前</div>
        </div>
      </div>
      <div class="line-normal-icon-wrapper"><img src="5.jpg"/></div>
    </div>
    <div class="line-btn-delete"><button>刪除</button></div>
  </div>
</div>
<div class="line-wrapper">
  <div class="line-scroll-wrapper">
    <div class="line-normal-wrapper">
      <div class="line-normal-left-wrapper">
        <div class="line-normal-avatar-wrapper"><img src="2.jpg" /></div>
        <div class="line-normal-info-wrapper">
          <div class="line-normal-user-name">喬巴</div>
          <div class="line-normal-msg">你看不到我哦</div>
          <div class="line-normal-time">1分鐘前</div>
        </div>
      </div>
      <div class="line-normal-icon-wrapper"><img src="6.jpg"/></div>
    </div>
    <div class="line-btn-delete"><button>刪除</button></div>
  </div>
</div>
<div class="line-wrapper">
  <div class="line-scroll-wrapper">
    <div class="line-normal-wrapper">
      <div class="line-normal-left-wrapper">
        <div class="line-normal-avatar-wrapper"><img src="3.jpg" /></div>
        <div class="line-normal-info-wrapper">
          <div class="line-normal-user-name">賤行賤遠</div>
          <div class="line-normal-msg">回憶裡想起模糊的小時候,雲朵漂浮在藍藍的天空,那時的你說,要和我手牽手,一起走到時間的盡頭</div>
          <div class="line-normal-time">1分鐘前</div>
        </div>
      </div>
      <div class="line-normal-icon-wrapper"><img src="7.jpg"/></div>
    </div>
    <div class="line-btn-delete"><button>刪除</button></div>
  </div>
</div>
<div class="line-wrapper">
  <div class="line-scroll-wrapper">
    <div class="line-normal-wrapper">
      <div class="line-normal-left-wrapper">
        <div class="line-normal-avatar-wrapper"><img src="4.png" /></div>
        <div class="line-normal-info-wrapper">
          <div class="line-normal-user-name">小黃人</div>
          <div class="line-normal-msg">哈哈哈哈哈……暑假來看小黃人電影哦~哈哈哈……</div>
          <div class="line-normal-time">1分鐘前</div>
        </div>
      </div>
      <div class="line-normal-icon-wrapper"><img src="8.jpg"/></div>
    </div>
    <div class="line-btn-delete"><button>刪除</button></div>
  </div>
</div>
</body>
</html>

總結

程式碼還比較粗糙,存在很多bug,也有些地方不是那麼絕對。比如當我按下時是在第一條記錄,然後擡起時是在第二條記錄,那麼這時候滑動將是第一條記錄。但是這個看具體需求了,如果你覺得滑動的物件應該以按下去時的物件為準的話,那就不管在哪擡起都滑動那個按下時的物件;如果你覺得滑動的物件應該是擡起時的物件,那也沒問題,或者你覺得按下和擡起時不是同一個物件就不滑動任何物件那也行。總之,看需求。

大家可以下載原始碼試一試哈~

原始碼請戳:原始碼下載

// 個人學習記錄,大神勿噴
// [email protected]
// 2015/6/5
// 最後更新 2016/9/6

相關推薦

基於jQuery出現刪除按鈕

最近在做專案的時候遇到了個需求,在網頁上實現類似於QQ會話列表那樣子的左滑出現刪除按鈕的效果,於是嘗試著寫了一個,寫出來與大家交流分享,大神勿噴。 基本要求 由於我們是在做一個跨平臺的APP,裡面部分介面其實就是WebView載入的網頁,因此需要使用網頁

出現刪除按鈕,右隱藏

<!doctype html> <html> <head> <meta charset="utf-8"> <title>左劃出現刪除按鈕,右滑隱藏</title> <script src="http://lib

Android仿QQ和iOS的ListView出現刪除和置頂等操作,可自定義選單

一:介紹 大家在專案中可能會有對ListView向左滑動的時候出現刪除,置頂等等操作的需求,例如QQ聊天列表左滑,iOS中左滑刪除等等,下面就介紹一下如何實現這種效果 二:先給大家展示效果圖,先睹為快 三:實現步驟 1.這種效果的ListView是自定義的控制元件,開源庫的下載地址是

Android 實現出現刪除選項

滑動刪除的部分主要包含兩個部分, 一個是內容區域(用於放置正常顯示的view),另一個是操作區域(用於放置刪除按鈕)。預設情況下,操作區域是不顯示的,內容區域的大小是填充整個容 器,操作區域始終位於內容區域的右面。當開始滑動的時候,整個容器中的所有子view都像

tableview出現刪除按鈕

首先在tableView裡面實現cell的左滑刪除功能是挺簡單的,相信大家都懂得怎麼做。但是,當有多個tableView放在一個scrollView裡面的時候,會產生一系列的問題。 問題1:       scrollView在滑倒最邊上(左或右)的時候,為了提醒使用者已經滑到最邊上了(左或右),再繼續向左(

關於tableview的知識總結,cell出現刪除、置頂按鈕

tableview是一個表檢視控制元件,在ios開發過程中用處最多的一個控制元件。它繼承與UIScrollView,有兩種樣式 UITableViewStyleGrouped和UITableViewStylePlain。使用表檢視必須遵循UITableViewDataSou

操作(刪除,置頂等。。。)

在滑動列表中,常常會有左滑出現刪除,置頂操作的需求,如下qq的左滑效果: 今天也來實現下類似的效果,可供大家參考: 1.實現原理 原理圖 2.實現自定義左滑View 1.新增View 首先在自定義V

tableView 編輯 刪除或其他操作

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {     return YES; //tableView可編輯 } -

使用MUI 實現模仿QQ向滑動出現刪除,編輯的程式碼

/* 使出現的錯誤隱藏[Intervention] Unable to preventDefault inside passive event listener due to target being treated as */

去除input輸入框預設在ie或者edge下出現刪除按鈕

  當使用input輸入框的時候,預設情況下在後面會出現刪除按鈕,這個時候需要程式碼去去除,去除ie下的刪除按鈕程式碼如下: ::-ms-clear{display: none;} ::-ms-reveal{display: none;} 去除edge下的刪除按鈕程式

基於JQuery的購物車新增刪除以及結算功能

前段時間瞭解到購物車結算算是一個難點部分,在網上也找了一些,但是網上除了外掛之外,就是一些半成品,比如一部分只有新增刪除效果,另一部分只有結算功能,很少見到整合在一起的購物車效果,因此自己寫了一個,方便大家檢視 (新增效果沒有飛入,實在懶得寫動畫效果了,湊合看吧) HTM

仿ios簡訊列表滑動出現刪除按鈕

最近還沒找到工作所以在宿舍有點閒,所以呢就自己寫了這麼一個例子。之前網上有很多人寫過類似的文章或demo,github上面也有開源專案。但是,老是copy別人程式碼也怪沒意思的,於是就自己嘗試著自己寫唄。廢話多了先來看下效果咯: 執行效果: 1、實現思路

用ionic做的列表向滑動,出現刪除等功能按鈕

ann 需要 balance -o tails details edate sts tran 廢話不多說,直接上代碼 html代碼: <!--列表--><ul class="lists" ng-repeat="list in lists"> <

仿QQ刪除基於RecyclerView】

這是我github開源專案,目前測試階段,歡迎大家使用提意見!   https://github.com/SineyCoder/LeftSlideView   使用步驟   新增倉庫 allprojects { rep

自定義UITableView實現自定義刪除按鈕及多按鈕,拖拽cell和表頭進行排序

本文介紹了能拖拽cell和表頭進行排序的自定義UITableView,並且能自定義左滑顯示的UIButton樣式。 先看左滑自定義按鈕效果圖  :     override func tableView(_ tableView: UITableView, editA

jQuery實現移動端刪除功能

在手機移動端,經常需要實現類似微信聊天工具中的左滑動刪除和右滑動恢復功能。 這裡,我們可以直接使用jQuery來實現該效果。 基本原理: 利用jQuery中的touchstart、touchmo

基於JS實現移動端刪除功能

HTML <div class="wrap pay-wrap" id="lists"> @foreach (var item in Model) { <div class="pay-list" style="h

菜單(刪除、置頂)

gin 所有 nbsp func stl lis mod cli img <div class="xinzhibox"> <div class="list"> <div class="xinzhilis

ionic之刪除

scala link rep false clas itl reat edi repeat <html ng-app="ionicApp"> <head> <meta charset="utf-8"> <meta name

前端 html h5 移動端 手機端 仿ios刪除效果

es2017 b- open translate def sna 技術 9.png replace 實現功能:左滑列表項(<li class="route-item" ></li>),出現刪除按鈕(<div class="removeJs"&