この記事では、シンプルな DrawerLayout (Android の DrawerLayout に似た) レイアウト コンポーネントの実装を紹介します。この記事を通じて、Vue.js に基づくサイドスライド メニュー コンポーネントの実装コードを一緒に学びましょう
この記事では、シンプルな DrawerLayout (似たような) レイアウト コンポーネントを紹介します。 Android の DrawerLayout) レイアウト コンポーネントの実装は Vue.js に基づいています。導入した内容はvue-drawer-layoutコンポーネント化されています。
前書き
ご興味がございましたら、まず携帯電話でこの QR コードをスキャンするか、私
をクリックしてから、ページの左上隅にあるアバターをクリックしてドロワーを開くか、右または左にドラッグして確認してください。携帯電話で QQ を開いたときの以下の GIF の効果は非常によく似ています:)
Google は正式にこのレイアウトを DrawerLayout (ドロワー ナビゲーション バー) と呼んでいます。では、どうやってそれを達成するのでしょうか? メインムービーを始めましょう!
HTML 構造
ページ構造は非常にシンプルで、ドロワーとメイン コンテナーがあり、コンテンツはスロットを使用して外部からカスタマイズできます。
<p class="drawer-layout"> <!--抽屉--> <p class="drawer-wrap"> <slot name="drawer"></slot> </p> <!--主容器--> <p class="content-wrap"> <!--遮罩--> <p class="drawer-mask"></p> <slot name="content"></slot> </p> </p>
最初は引き出しが左画面の外に隠れているので、左:-100%にして外に完全に隠します
Touchを使用
まず、ブラウザがtouchEvent
let isTouch = 'ontouchstart' in window; let mouseEvents = isTouch ? { down: 'touchstart', move: 'touchmove', up: 'touchend', over: 'touchstart', out: 'touchend' } : { down: 'mousedown', move: 'mousemove', up: 'mouseup', over: 'mouseover', out: 'mouseout' };
をサポートしているかどうかを確認しますタッチダウン イベントをバインドします
document.addEventListener(mouseEvents.down, initDrag, false);
まず、押された指の x 座標は startX としてマークされ、スライド中の指の x 座標は nowX としてマークされ、ドロワーの x 座標オフセットを定義します。 startPos
let startX, nowX, startPos;
としてマークされています。 touchstart がトリガーされると、開始位置を記録し、touchmove をバインドします。 touchEvent の場合は、e.clientX を通じて現在の x 座標を取得します。 [0].clientX
const initDrag = function (e) { startX = e.clientX || e.changedTouches[0].clientX; //记录手指按下的位置 startPos = this.pos; //记录drawer的上次位置 document.addEventListener(mouseEvents.move, drag, false); document.addEventListener(mouseEvents.up, removeDrag, false); }.bind(this); const drag = function (e) { nowX = e.clientX || e.changedTouches[0].clientX; //滑动中手指的位置x坐标 let pos = startPos + nowX - startX; pos = Math.min(width, pos); //不能超过滑动最大值 pos = Math.max(0, pos); //不能小于0 this.pos = pos; //设置滚动距离为拖动的距离 }.bind(this);
すると、指のスライド距離はnowX - startX、現在のドロワーの位置はstartPos + nowX - startXになります。 このように、ドロワーは指に追従して右に移動します。設定した最大抗力値を超えないこと。
垂直スライドと水平スライドを区別してください
次に、指でメインコンテンツを垂直にスクロールするときに、指を右にスライドすると引き出しもドラッグされます。やるべきことは一つ:縦方向のスライドと横方向のスライドを区別する
もちろん方法はたくさんありますが、ここでは三角関数を使って決定する方法をご紹介します
上の図の各矢印が指のスライド方向であると仮定します。 、緑の矢印はドラッグできることを意味します。ドロワーでは、赤い矢印はドラッグできないことを意味します (赤い矢印には x 座標のオフセットもあることに注意してください)。つまり、ドロワーをドラッグできない場合は、垂直スクロールなどのデフォルトのイベントをトリガーする必要があります。
指を押してタッチスタートをトリガーすると、最初の位置 P 0 が記録されます。指をスライドすると、最初のタッチ移動がトリガーされ、位置 P 1 が記録されます。P 0 から P 1 までのベクトルを S (これは許してください) Soul Painter)
この時、∠θが一定の値、例えば30度より大きい場合、ドロワーのドラッグではなく縦スクロール操作である可能性があることが容易に分かります。したがって、判定条件はy/x>tan30°で求めることができます
:
if (isVerticle === undefined) isVerticle = Math.abs(nowY - startY) / Math.abs(nowX - startX) > (Math.sqrt(3) / 3);
isVerticleがtrueの場合、引き出しのドラッグは行われません
引き出しを動かしてみましょう
css3のtransition属性を利用しますドロワーに遷移アニメーションを持たせるには、ここに移動クラスを記述します
.moving transition transform .3s ease
ドラッグ時に遷移アニメーションを追加する必要はありません (指をたどる必要があります)。指を離すときに必要です。
<p class="drawer-wrap" :class="{'moving':moving,'will-change':willChange}" :style="{width:`${width}px`,left:`-${width)}px`,transform:`translate3d(${pos}px,0,0)`}"> <slot name="drawer"></slot> </p>
そのため、touchend イベント メソッドをバインドするときは、次の手順を実行する必要があります
const removeDrag = function (e) { if (isVerticle !== undefined) { if (!isVerticle) {//当判定为抽屉拖动才进入 let pos = this.pos; this.visible = pos > width * 3 / 5 //当前位置如果大于总宽度的3/5就判定为全部展开抽屉,否则将抽屉弹回隐藏 if (this.pos > 0 && this.pos < width) this.moving = true;//如果位置已经处于最小值或最大值处,不需要有动画效果了 } this.pos = this.visible ? width : 0; } if (!this.moving) { this.willChange = false; //留个悬念 } isVerticle = undefined; //取消touchmove和touchend事件绑定 document.removeEventListener(mouseEvents.move, drag, false); document.removeEventListener(mouseEvents.up, removeDrag, false); }.bind(this);
上記のコードには this.willChange = false が表示されますが、これは何を行うのでしょうか?以下では、css の will-change メソッドを紹介します
。will-change
will-changetransform
CSS 属性 will-change は、要素にどのような変更が加えられるかをブラウザーに伝える方法を Web 開発者に提供します。プロセッサは、要素の属性が実際に変更される前に、対応する最適化の準備を事前に行うことができます。 この種の最適化により、複雑な計算作業の一部を事前に準備できるため、ページの応答がより速く、より敏感になります。
実際、ブラウザ ドロワーが touchstart で移動する可能性があることを事前にブラウザ ドロワーに通知できます
const initDrag = function (e) { //... this.willChange = true; }.bind(this);
もちろん、transitionend イベントの後にトランジションと will-change を削除することを忘れずに、ブラウザをしばらく休ませます。しばらくお待ちください~
他に最適化できるものは何ですか?
上記の主な機能は基本的に実装されていますが、他に最適化できる点はありますか?
え?パッシブ
って一体何?
网站使用被动事件侦听器以提升滚动性能,在您的触摸和滚轮事件侦听器上设置 passive 选项可提升滚动性能具体看这里
原来这是现代浏览器的一个新特性,我们需要以新的方式来绑定我们的touch事件,当然首先先检测一下是否支持 passive
const supportsPassive = (() => { let supportsPassive = false; try { const opts = Object.defineProperty({}, 'passive', { get: function () { supportsPassive = true; } }); window.addEventListener("test", null, opts); } catch (e) { } return supportsPassive; })();
于是我们的绑定事件代码变成这样
document.addEventListener(mouseEvents.move, drag, supportsPassive ? {passive: true} : false);
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在React Native中使用prop-types如何实现属性确认
以上がVue でサイドスライド メニュー コンポーネントを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。