Vue에서 측면 슬라이딩 메뉴 구성요소를 구현하는 방법

亚连
풀어 주다: 2018-06-20 10:45:05
원래의
3841명이 탐색했습니다.

이 글에서는 간단한 DrawerLayout(안드로이드의 DrawerLayout과 유사) 레이아웃 컴포넌트 구현을 소개합니다. 이 글을 통해 Vue.js 기반의 사이드 슬라이딩 메뉴 컴포넌트 구현 코드를 함께 배워보겠습니다.

이 글에서는 간단한 DrawerLayout(비슷한)을 소개합니다. Android의 DrawerLayout) 레이아웃에 대한 구성 요소 구현은 Vue.js를 기반으로 합니다. 소개된 내용을 vue-drawer-layout 컴포넌트로 만들었습니다.

머리말

관심이 있으시면 먼저 휴대폰으로 이 QR 코드를 스캔하거나 저를 클릭하세요

그런 다음 페이지 왼쪽 상단에 있는 아바타를 클릭하여 서랍을 열거나 오른쪽이나 왼쪽으로 드래그해 보세요. 아래 gif의 효과는 휴대폰에서 QQ를 열었을 때 매우 유사해 보입니다. :)

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>
로그인 후 복사

서랍은 처음에는 왼쪽 화면 바깥쪽에 숨겨져 있으므로 left:-100%로 설정하면 바깥에서 완전히 숨겨집니다

터치 사용

먼저 브라우저가 touchEvent를 지원하는지 확인하세요

let isTouch = &#39;ontouchstart&#39; in window;
  let mouseEvents = isTouch ?
    {
      down: &#39;touchstart&#39;,
      move: &#39;touchmove&#39;,
      up: &#39;touchend&#39;,
      over: &#39;touchstart&#39;,
      out: &#39;touchend&#39;
    } :
    {
      down: &#39;mousedown&#39;,
      move: &#39;mousemove&#39;,
      up: &#39;mouseup&#39;,
      over: &#39;mouseover&#39;,
      out: &#39;mouseout&#39;
    };
로그인 후 복사

터치다운 이벤트 바인딩

document.addEventListener(mouseEvents.down, initDrag, false);
로그인 후 복사

먼저 몇 가지 변수를 정의합니다. 누른 손가락의 x좌표는 startX로 표시되고, 슬라이딩하는 동안 손가락의 x좌표는 nowX로 표시되며, 서랍의 x좌표 오프셋은 다음과 같습니다. startPos

let startX, nowX, startPos;
로그인 후 복사

로 표시됩니다. touchstart가 트리거되면 시작 위치를 기록하고 touchmove를 바인딩합니다. 참고: mouseEvent인 경우 e.clientX를 통해 현재 x 좌표를 가져옵니다. touchEvent인 경우 e.changedTouches를 통해 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 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인 경우 서랍의 드래그가 수행되지 않습니다

Let the Drawer move

css3의 전환 속성을 사용합니다. 서랍에 전환 애니메이션을 적용하려면 여기에 이동 클래스를 작성하세요

.moving
  transition transform .3s ease
로그인 후 복사

클래스 바인딩을 추가하는 것을 잊지 마세요. 드래그할 때 전환 애니메이션이 필요하지 않으며(손가락을 따라야 함) 전환 애니메이션은 손가락을 뗄 때 필요합니다.

<p class="drawer-wrap" :class="{&#39;moving&#39;:moving,&#39;will-change&#39;: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는 웹 개발자에게 요소에 어떤 변경 사항이 적용될지 알려주는 방법을 제공합니다. 프로세서는 요소 속성이 실제로 변경되기 전에 미리 상응하는 최적화 준비를 할 수 있습니다. 이 최적화를 통해 복잡한 계산 작업의 일부를 미리 준비하여 페이지의 반응성과 반응성을 높일 수 있습니다.

실제로 터치스타트에서 브라우저 서랍이 옮겨질 수 있음을 미리 브라우저 서랍에 알릴 수 있습니다

const initDrag = function (e) {
  //...
  this.willChange = true;
}.bind(this);
로그인 후 복사

물론 전환을 제거하는 것을 잊지 마세요. 잠시만요~

또 어떤 것을 최적화할 수 있나요?

위에서 언급한 주요 기능들은 기본적으로 구현되어 있는데, 또 최적화할 수 있는 부분은 없나요?

에? 패시브

란 도대체 무엇인가요?

网站使用被动事件侦听器以提升滚动性能,在您的触摸和滚轮事件侦听器上设置 passive 选项可提升滚动性能具体看这里

原来这是现代浏览器的一个新特性,我们需要以新的方式来绑定我们的touch事件,当然首先先检测一下是否支持 passive

const supportsPassive = (() => {
  let supportsPassive = false;
  try {
    const opts = Object.defineProperty({}, &#39;passive&#39;, {
      get: function () {
        supportsPassive = true;
      }
    });
    window.addEventListener("test", null, opts);
  } catch (e) {
  }
  return supportsPassive;
})();
로그인 후 복사

于是我们的绑定事件代码变成这样

document.addEventListener(mouseEvents.move, drag, supportsPassive ? {passive: true} : false);
로그인 후 복사

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

Bootstrap栅格系统(详细教程)

在jQuery中如何实现点击DIV触发点击CheckBox

在React Native中使用prop-types如何实现属性确认

在jQuery中如何实现弹窗下底部页面禁止滑动效果

$refs访问Vue中的DOM(详细教程)

위 내용은 Vue에서 측면 슬라이딩 메뉴 구성요소를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿