mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-05-21 21:41:53 +00:00
enable swipe to open or close sidenav (#429)
* implement swipe on Sidenav * update the docs * prefix props with md- and update from destroyed to beforeDestroy * refactor to clarify logic
This commit is contained in:
parent
add429966e
commit
65c1ff8453
2 changed files with 116 additions and 2 deletions
|
|
@ -7,6 +7,36 @@
|
|||
|
||||
<div slot="api">
|
||||
<api-table name="md-sidenav">
|
||||
<md-table slot="properties">
|
||||
<md-table-header>
|
||||
<md-table-row>
|
||||
<md-table-head>Name</md-table-head>
|
||||
<md-table-head>Type</md-table-head>
|
||||
<md-table-head>Description</md-table-head>
|
||||
</md-table-row>
|
||||
</md-table-header>
|
||||
|
||||
<md-table-body>
|
||||
<md-table-row>
|
||||
<md-table-cell>md-swipeable</md-table-cell>
|
||||
<md-table-cell><code>Boolean</code></md-table-cell>
|
||||
<md-table-cell>Enable the swipe functionality. Default <code>false</code></md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>md-swipe-threshold</md-table-cell>
|
||||
<md-table-cell><code>Number</code></md-table-cell>
|
||||
<md-table-cell>Set the initial threshold for the swipe when it's closed. Default <code>15</code></md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>md-swipe-distance</md-table-cell>
|
||||
<md-table-cell><code>Number</code></md-table-cell>
|
||||
<md-table-cell>Set the swipe distance needed to open/close the sidenav. Default <code>100</code></md-table-cell>
|
||||
</md-table-row>
|
||||
</md-table-body>
|
||||
</md-table>
|
||||
|
||||
<md-table slot="classes">
|
||||
<md-table-header>
|
||||
<md-table-row>
|
||||
|
|
@ -102,7 +132,7 @@
|
|||
<p>Open console to see the events</p>
|
||||
</div>
|
||||
|
||||
<md-sidenav class="md-left" ref="leftSidenav" @open="open('Left')" @close="close('Left')">
|
||||
<md-sidenav class="md-left" ref="leftSidenav" @open="open('Left')" @close="close('Left')" md-swipeable>
|
||||
<md-toolbar class="md-large">
|
||||
<div class="md-toolbar-container">
|
||||
<h3 class="md-title">Sidenav content</h3>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<md-backdrop class="md-sidenav-backdrop" @close="close"></md-backdrop>
|
||||
<md-backdrop class="md-sidenav-backdrop" @close="close" ref="backdrop"></md-backdrop>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -20,6 +20,17 @@
|
|||
};
|
||||
},
|
||||
mixins: [theme],
|
||||
props: {
|
||||
mdSwipeable: Boolean,
|
||||
mdSwipeThreshold: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
mdSwipeDistance: {
|
||||
type: Number,
|
||||
default: 100
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return this.mdVisible && 'md-active';
|
||||
|
|
@ -45,7 +56,80 @@
|
|||
} else {
|
||||
this.open();
|
||||
}
|
||||
},
|
||||
isHorizontallyInside(positionX) {
|
||||
return positionX > 0 && positionX < this.mountedRect.left + this.mountedRect.width;
|
||||
},
|
||||
isVerticallyInside(positionY) {
|
||||
return positionY > 0 && positionY < this.mountedRect.top + this.mountedRect.height;
|
||||
},
|
||||
isFromStartWhenClosed(positionX) {
|
||||
if (this.mdVisible) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return positionX < this.mdSwipeThreshold;
|
||||
},
|
||||
handleTouchStart(event) {
|
||||
const positionX = event.touches[0].clientX - this.mountedRect.left;
|
||||
const positionY = event.touches[0].clientY - this.mountedRect.top;
|
||||
|
||||
if (
|
||||
!this.isHorizontallyInside(positionX) ||
|
||||
!this.isVerticallyInside(positionY) ||
|
||||
!this.isFromStartWhenClosed(positionX)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialTouchPosition = positionX;
|
||||
this.canMove = true;
|
||||
},
|
||||
handleTouchEnd() {
|
||||
this.canMove = false;
|
||||
this.initialTouchPosition = null;
|
||||
},
|
||||
handleTouchMove(event) {
|
||||
if (!this.canMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
const positionX = event.touches[0].clientX;
|
||||
|
||||
const difference = this.mdVisible
|
||||
? this.initialTouchPosition - positionX
|
||||
: positionX - this.initialTouchPosition;
|
||||
|
||||
const action = this.mdVisible
|
||||
? 'close'
|
||||
: 'open';
|
||||
|
||||
if (difference > this.mdSwipeDistance) {
|
||||
this[action]();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.mdSwipeable) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.mountedRect = this.$refs.backdrop.$el.getBoundingClientRect();
|
||||
this.initialTouchPosition = null;
|
||||
this.canMove = false;
|
||||
|
||||
document.addEventListener('touchstart', this.handleTouchStart);
|
||||
document.addEventListener('touchend', this.handleTouchEnd);
|
||||
document.addEventListener('touchmove', this.handleTouchMove);
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.mdSwipeable) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.removeEventListener('touchstart', this.handleTouchStart);
|
||||
document.removeEventListener('touchend', this.handleTouchEnd);
|
||||
document.removeEventListener('touchmove', this.handleTouchMove);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue