이 글에서는 간단한 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 = '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를 바인딩합니다. 참고: 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="{'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는 웹 개발자에게 요소에 어떤 변경 사항이 적용될지 알려주는 방법을 제공합니다. 프로세서는 요소 속성이 실제로 변경되기 전에 미리 상응하는 최적화 준비를 할 수 있습니다. 이 최적화를 통해 복잡한 계산 작업의 일부를 미리 준비하여 페이지의 반응성과 반응성을 높일 수 있습니다.
실제로 터치스타트에서 브라우저 서랍이 옮겨질 수 있음을 미리 브라우저 서랍에 알릴 수 있습니다
const initDrag = function (e) { //... this.willChange = true; }.bind(this);
물론 전환을 제거하는 것을 잊지 마세요. 잠시만요~
또 어떤 것을 최적화할 수 있나요?
위에서 언급한 주요 기능들은 기본적으로 구현되어 있는데, 또 최적화할 수 있는 부분은 없나요?
에? 패시브
란 도대체 무엇인가요?
网站使用被动事件侦听器以提升滚动性能,在您的触摸和滚轮事件侦听器上设置 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!