mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-04-02 22:30:31 +00:00
Make menu open in a correct position
This commit is contained in:
parent
79832bfba6
commit
5d961b45ef
6 changed files with 197 additions and 25 deletions
|
|
@ -13,6 +13,42 @@
|
|||
<md-menu-item>My Item 3</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
|
||||
<md-menu md-direction="bottom left">
|
||||
<md-button class="md-icon-button" md-menu-trigger>
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
|
||||
<md-menu-content>
|
||||
<md-menu-item>My Item 1</md-menu-item>
|
||||
<md-menu-item>My Item 2</md-menu-item>
|
||||
<md-menu-item>My Item 3</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
|
||||
<md-menu md-direction="top left">
|
||||
<md-button class="md-icon-button" md-menu-trigger>
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
|
||||
<md-menu-content>
|
||||
<md-menu-item>My Item 1</md-menu-item>
|
||||
<md-menu-item>My Item 2</md-menu-item>
|
||||
<md-menu-item>My Item 3</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
|
||||
<md-menu md-direction="top right">
|
||||
<md-button class="md-icon-button" md-menu-trigger>
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
|
||||
<md-menu-content>
|
||||
<md-menu-item>My Item 1</md-menu-item>
|
||||
<md-menu-item>My Item 2</md-menu-item>
|
||||
<md-menu-item>My Item 3</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</demo-example>
|
||||
</div>
|
||||
|
||||
|
|
@ -25,3 +61,9 @@
|
|||
</div>
|
||||
</demo-page>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.md-menu {
|
||||
margin-right: 50px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
"autosize": "^3.0.17",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
|
||||
"scopedQuerySelectorShim": "github:lazd/scopedQuerySelectorShim",
|
||||
"transitionEnd": "^1.0.2",
|
||||
"vue": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
|
||||
$menu-base-width: 56px;
|
||||
|
||||
.md-menu {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.md-menu-content {
|
||||
width: $menu-base-width * 3;
|
||||
min-width: $menu-base-width * 1.5;
|
||||
max-width: $menu-base-width * 3;
|
||||
max-width: $menu-base-width * 7;
|
||||
min-height: 64px;
|
||||
max-height: 256px;
|
||||
padding: 8px 0;
|
||||
|
|
@ -23,44 +28,41 @@ $menu-base-width: 56px;
|
|||
border-radius: 2px;
|
||||
box-shadow: $material-shadow-2dp;
|
||||
opacity: 0;
|
||||
transform: scale3D(.85, .7, 1);
|
||||
transition: $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
opacity .25s $swift-ease-in-timing-function,
|
||||
top .25s $swift-ease-in-timing-function,
|
||||
transform 0s .25s $swift-ease-in-timing-function;
|
||||
transform: scale3D(.85, .85, 1);
|
||||
transition: width $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
opacity .2s $swift-ease-in-timing-function,
|
||||
transform .15s .1s $swift-ease-in-timing-function;
|
||||
color: rgba(#212121, .87);
|
||||
|
||||
&.md-active {
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
transform: scale3D(1, 1, 1);
|
||||
transform-origin: center top;
|
||||
transition: $swift-ease-out;
|
||||
transition-duration: .25s;
|
||||
transition-property: opacity, transform, top;
|
||||
transform-origin: center;
|
||||
transition: width $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
opacity .2s $swift-ease-out-timing-function,
|
||||
transform .15s .1s $swift-ease-out-timing-function;
|
||||
|
||||
> * {
|
||||
opacity: 1;
|
||||
transition: $swift-ease-in;
|
||||
transition-duration: .15s;
|
||||
transition-delay: .1s;
|
||||
}
|
||||
}
|
||||
|
||||
&.md-size-1 {
|
||||
max-width: $menu-base-width * 1.5;
|
||||
width: $menu-base-width * 1.5;
|
||||
}
|
||||
|
||||
@for $i from 2 through 7 {
|
||||
&.md-size-#{$i} {
|
||||
max-width: $menu-base-width * $i;
|
||||
width: $menu-base-width * $i;
|
||||
}
|
||||
}
|
||||
|
||||
> * {
|
||||
opacity: 0;
|
||||
transition: $swift-ease-out;
|
||||
transition-duration: .25s;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +85,7 @@ $menu-base-width: 56px;
|
|||
|
||||
&:hover {
|
||||
background-color: rgba(#000, .12);
|
||||
transition: $swift-ease-out;
|
||||
}
|
||||
|
||||
.md-menu-item-content {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,19 @@
|
|||
<style lang="scss" src="./mdMenu.scss"></style>
|
||||
|
||||
<script>
|
||||
import 'transitionEnd';
|
||||
|
||||
let transitionEnd = window.transitionEnd;
|
||||
|
||||
export default {
|
||||
props: {
|
||||
mdSize: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
default: 0
|
||||
},
|
||||
mdDirection: {
|
||||
type: String,
|
||||
default: 'bottom right'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -40,17 +48,131 @@
|
|||
addNewMenuContentClass() {
|
||||
this.menuContent.classList.add('md-size-' + this.mdSize);
|
||||
},
|
||||
closeOnOffClick(event) {
|
||||
if (!this.$el.contains(event.target)) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
calculateMenuContentPos() {
|
||||
let menuTriggerRect = this.menuTrigger.getBoundingClientRect();
|
||||
let margin = 8;
|
||||
let top;
|
||||
let left;
|
||||
let origin;
|
||||
|
||||
switch (this.mdDirection) {
|
||||
case 'bottom left':
|
||||
top = menuTriggerRect.top;
|
||||
left = menuTriggerRect.left - this.menuContent.offsetWidth + menuTriggerRect.width;
|
||||
origin = 'right top';
|
||||
|
||||
if (left <= margin) {
|
||||
left = margin;
|
||||
origin = 'center top';
|
||||
}
|
||||
|
||||
if (top <= margin) {
|
||||
top = margin;
|
||||
origin = 'right center';
|
||||
}
|
||||
|
||||
if (left <= margin && top <= margin) {
|
||||
origin = 'center';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'top right':
|
||||
top = menuTriggerRect.top + menuTriggerRect.height - this.menuContent.offsetHeight;
|
||||
left = menuTriggerRect.left;
|
||||
origin = 'left bottom';
|
||||
|
||||
if (left <= margin) {
|
||||
left = margin;
|
||||
origin = 'center bottom';
|
||||
}
|
||||
|
||||
if (top <= margin) {
|
||||
top = margin;
|
||||
origin = 'left center';
|
||||
}
|
||||
|
||||
if (left <= margin && top <= margin) {
|
||||
origin = 'center';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'top left':
|
||||
top = menuTriggerRect.top + menuTriggerRect.height - this.menuContent.offsetHeight;
|
||||
left = menuTriggerRect.left - this.menuContent.offsetWidth + menuTriggerRect.width;
|
||||
origin = 'right bottom';
|
||||
|
||||
if (left <= margin) {
|
||||
left = margin;
|
||||
origin = 'center bottom';
|
||||
}
|
||||
|
||||
if (top <= margin) {
|
||||
top = margin;
|
||||
origin = 'right center';
|
||||
}
|
||||
|
||||
if (left <= margin && top <= margin) {
|
||||
origin = 'center';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
top = menuTriggerRect.top;
|
||||
left = menuTriggerRect.left;
|
||||
origin = 'left top';
|
||||
|
||||
if (left <= margin) {
|
||||
left = margin;
|
||||
origin = 'center top';
|
||||
}
|
||||
|
||||
if (top <= margin) {
|
||||
top = margin;
|
||||
origin = 'left center';
|
||||
}
|
||||
|
||||
if (left <= margin && top <= margin) {
|
||||
origin = 'center';
|
||||
}
|
||||
}
|
||||
|
||||
this.menuContent.style.transformOrigin = origin;
|
||||
this.menuContent.style.top = top + 'px';
|
||||
this.menuContent.style.left = left + 'px';
|
||||
},
|
||||
open() {
|
||||
document.body.appendChild(this.menuContent);
|
||||
document.addEventListener('click', this.closeOnOffClick);
|
||||
|
||||
this.calculateMenuContentPos();
|
||||
|
||||
getComputedStyle(this.menuContent).top;
|
||||
this.menuContent.classList.add('md-active');
|
||||
this.active = true;
|
||||
},
|
||||
close() {
|
||||
transitionEnd(this.menuContent).bind(() => {
|
||||
document.body.removeChild(this.menuContent);
|
||||
document.removeEventListener('click', this.closeOnOffClick);
|
||||
transitionEnd(this.menuContent).unbind();
|
||||
this.active = false;
|
||||
});
|
||||
|
||||
this.menuContent.classList.remove('md-active');
|
||||
},
|
||||
toggle() {
|
||||
if (this.active) {
|
||||
this.menuContent.classList.remove('md-active');
|
||||
document.body.removeChild(this.menuContent);
|
||||
this.active = false;
|
||||
this.close();
|
||||
} else {
|
||||
document.body.appendChild(this.menuContent);
|
||||
|
||||
getComputedStyle(this.menuContent).display;
|
||||
this.menuContent.classList.add('md-active');
|
||||
this.active = true;
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="md-menu-item" v-md-ink-ripple>
|
||||
<div class="md-menu-item" v-md-ink-ripple @click="$emit('click')">
|
||||
<div class="md-menu-item-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4312,6 +4312,10 @@ tough-cookie@~2.3.0:
|
|||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.1.tgz#99c77dfbb7d804249e8a299d4cb0fd81fef083fd"
|
||||
|
||||
transitionEnd:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/transitionEnd/-/transitionEnd-1.0.2.tgz#1914db5b45a7efdc34a01af69285a3a693871633"
|
||||
|
||||
trim-newlines@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
|
||||
|
|
|
|||
Loading…
Reference in a new issue