この記事では主に、jQuery に基づいて左側のスライドに表示される削除ボタンの例を紹介します。詳細なコードはここにまとめられています。必要な方は参考にしていただければ幸いです。
最近、プロジェクトに取り組んでいるときに、Web ページの QQ 会話リストと同様の、左スワイプ時の削除ボタンのエフェクトを実装したいと思ったので、作成してみんなに共有してみました。私を批判しないでください。
基本要件
クロスプラットフォームAPPを作成しているため、インターフェイスの一部は実際にはWebViewによってロードされるWebページであるため、この効果を実現するにはWebページを使用する必要があります: 左にスライドすると、削除ボタンが表示され、右にスライドすると削除ボタンが非表示になります。
完成品のサンプル写真
さて、まずは写真を撮りましょう。 PCブラウザとモバイルブラウザそれぞれでの効果は以下の通りです。
PC ブラウザ
モバイル ブラウザ
実装アイデア
私の実装アイデアを説明するために、説明を助けるために 2 つの写真を作成しました。
まず、図1をご覧ください。図では各行の幅をブラウザの幅を超えるように設定しており、超えた部分がボタンを配置する領域となります。ブラウザの最大幅を超えているため、この時点ではボタン領域は表示されず、左側の一般情報セクションのみが表示されます。
図1 通常状態
次に、左側の一般情報エリアを監視し、スライディングイベントを監視します(具体的な監視方法はまだ検討されていません)。左スワイプ イベントをリッスンするとき、ボタンが表示されるように対応する行を左にオフセットし、左の余分な部分はブロックされます (図 2 を参照)。
図2 左スライド状態
右にスライドすると、対応する行が左オフセットが0の時点に戻るだけです。
主要な実装方法
左右のスライドについては、一般情報エリアの margin-left を設定することで実装します。 margin-left を負の値に設定すると、左スライドが実現されます。マージンを再設定します -left が 0 の場合、右にスライドします。
スライドイベント監視では、マウス(指)の押下と離しを監視し、2点のX座標の差の符号に基づいて右にスライドするか左にスライドするかを判定することで実装されています。
完全なコード
なお、テスト時にChromeの通常モードとモバイルシミュレーターモードを使用しましたが、2つのモードのモニタリングが異なることが判明したので、少なくとも2種類のモニタリングを作成しました。そのうちの1人が処刑されます。他にもより良い適応方法があるかもしれませんが、ここでは焦点を当てません。もちろん、皆さんもアドバイスをいただければ幸いです。
コード部分に関しては、実はjQueryを使わなくても問題ありませんが、アニメーションのスライドやモニタリングなどは純粋なjsで書くこともできますが、ここでは主眼ではないのでjQueryを使ってみませんか?成功者は巨人の肩の上に立っていますが、私たちは jQuery を書くのが苦手です (。・`ω´・)
2015/11/13 更新
クラスメートが、コードは QQ モバイルにあると提案しましたブラウザと Opera モバイルブラウザなどではスライド効果がありません。おそらく投稿に記載されている理由を探したので、投稿内のヒントとそのクラスメートの優秀なクラスメートのヒントに基づいていくつかの修正を加えました。主に touchmove イベントでは、次のように、水平および垂直の座標変位を使用してデフォルト イベントをブロックするかどうかが決定されます:
// 横向位移大于纵向位移,阻止纵向滚动 if (Math.abs(delta.x) > Math.abs(delta.y)) { event.preventDefault(); }
2016/02/25 更新
qq_25558115 クラスメートが言及しました:レコードが 1 つある場合は、左にスワイプすると、他のレコードをスライドすると、左にスワイプしたレコードが元の位置に戻ります。そこで、簡単な実装を実行しました。主なアイデアは次のとおりです:
// 用一个变量记录上一次左滑的对象 var lastLeftObj; // 在左滑发生的时候,判定上一个左滑的对象是否存在,若存在,且不是当前被左滑的对象,则将其右滑 // 同时,记录新的左滑对象 // 在右滑发生时,将上一个左滑对象清空 if (左滑) { pressedObj左滑 lastLeftObj && lastLeftObj != pressedObj && lastLeftObj右滑 lastLeftObj = pressedObj; // 记录上一个左滑的对象 } else if (右滑) { pressedObj右滑 lastLeftObj = null; // 清空上一个左滑的对象 }
2016/09/06更新
Ma Canfaによって提起されたバグに従って修正:
右にスワイプするオブジェクトが右にスワイプされた場合のみ判断します( pressedObj) は最後です。オブジェクトを左にスライドし (lastLeftObj)、lastLeftObj をクリアするだけです。
if (pressedObj == lastLeftObj) {...}
girlyougoさんの提案に従い、「この行以外の領域をクリックすると現在の左スライドボタンをリセットする」機能を追加します。アイデアは、スライドの最後で pressedObj!=lastLeftObj を決定することです。つまり、クリック/スライドされたオブジェクトが別のオブジェクトであることがわかっています:
// 点击除当前左滑对象之外的任意其他位置 if (lastLeftObj && pressedObj != lastLeftObj) { $(lastLeftObj).animate({marginLeft:"0"}, 500); // 右滑 lastLeftObj = null; // 清空上一个左滑的对象 }
実際、上記の関数を追加した後、前述のバグが発生しました。上記はもう存在しません。ただし、バグを除去するコードの部分はここに保持されます。
更新された完全なコードは次のとおりです:
<!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> <p class="line-wrapper"> <p class="line-scroll-wrapper"> <p class="line-normal-wrapper"> <p class="line-normal-left-wrapper"> <p class="line-normal-avatar-wrapper"><img src="1.jpg" /></p> <p class="line-normal-info-wrapper"> <p class="line-normal-user-name">蜡笔小新</p> <p class="line-normal-msg">在同行的小伙伴中提到了你</p> <p class="line-normal-time">1分钟前</p> </p> </p> <p class="line-normal-icon-wrapper"><img src="5.jpg"/></p> </p> <p class="line-btn-delete"><button>删除</button></p> </p> </p> <p class="line-wrapper"> <p class="line-scroll-wrapper"> <p class="line-normal-wrapper"> <p class="line-normal-left-wrapper"> <p class="line-normal-avatar-wrapper"><img src="2.jpg" /></p> <p class="line-normal-info-wrapper"> <p class="line-normal-user-name">乔巴</p> <p class="line-normal-msg">你看不到我哦</p> <p class="line-normal-time">1分钟前</p> </p> </p> <p class="line-normal-icon-wrapper"><img src="6.jpg"/></p> </p> <p class="line-btn-delete"><button>删除</button></p> </p> </p> <p class="line-wrapper"> <p class="line-scroll-wrapper"> <p class="line-normal-wrapper"> <p class="line-normal-left-wrapper"> <p class="line-normal-avatar-wrapper"><img src="3.jpg" /></p> <p class="line-normal-info-wrapper"> <p class="line-normal-user-name">贱行贱远</p> <p class="line-normal-msg">回忆里想起模糊的小时候,云朵漂浮在蓝蓝的天空,那时的你说,要和我手牵手,一起走到时间的尽头</p> <p class="line-normal-time">1分钟前</p> </p> </p> <p class="line-normal-icon-wrapper"><img src="7.jpg"/></p> </p> <p class="line-btn-delete"><button>删除</button></p> </p> </p> <p class="line-wrapper"> <p class="line-scroll-wrapper"> <p class="line-normal-wrapper"> <p class="line-normal-left-wrapper"> <p class="line-normal-avatar-wrapper"><img src="4.png" /></p> <p class="line-normal-info-wrapper"> <p class="line-normal-user-name">小黄人</p> <p class="line-normal-msg">哈哈哈哈哈……暑假来看小黄人电影哦~哈哈哈……</p> <p class="line-normal-time">1分钟前</p> </p> </p> <p class="line-normal-icon-wrapper"><img src="8.jpg"/></p> </p> <p class="line-btn-delete"><button>删除</button></p> </p> </p> </body> </html>
概要
コードはまだ比較的ラフで、多くのバグがあり、いくつかの場所はそれほど絶対的ではありません。たとえば、押すと 1 番目のレコードに移動し、持ち上げると 2 番目のレコードに移動し、この時点でスライドは 1 番目のレコードに移動します。ただし、これは特定のニーズによって異なります。スライドするオブジェクトが押されたときのオブジェクトに基づく必要があると考える場合は、オブジェクトが持ち上げられる場所に関係なく、オブジェクトが押されたときにスライドする必要があります。持ち上げたときに、オブジェクトを押したときと持ち上げたときに同じオブジェクトではないと思われる場合は、スライドさせなくても大丈夫です。要するに、需要次第です。
関連推奨事項:
JSをベースに、モバイル端末上で左にスライドした際の削除ボタン機能を実装
ボタンをクリックした後に上記の入力内容を表示するAngular実装の詳細例
WeChatアプレットは、ボタンをクリックしてフォントの色を変更する機能を実装します
以上がjQueryは左にスライドして削除ボタンを表示するメソッドを実装していますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。