mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-05-09 07:54:43 +00:00
Create dialog opening from and closing to
This commit is contained in:
parent
2021637830
commit
40a4213b98
3 changed files with 144 additions and 54 deletions
|
|
@ -2,7 +2,7 @@
|
|||
<demo-page label="Components - Dialog">
|
||||
<div slot="examples">
|
||||
<demo-example label="Default" size="2">
|
||||
<md-dialog ref="dialog">
|
||||
<md-dialog md-open-from="#trigger" md-close-to="#trigger" ref="dialog">
|
||||
<div class="md-dialog-content">
|
||||
<form>
|
||||
<md-input-container>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<md-button class="md-primary md-raised" @click="closeDialog">Close</md-button>
|
||||
</md-dialog>
|
||||
|
||||
<md-button class="md-primary md-raised" @click="openDialog">Open</md-button>
|
||||
<md-button class="md-primary md-raised" id="trigger" @click="openDialog">Open</md-button>
|
||||
</demo-example>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +1,64 @@
|
|||
@import '../../core/stylesheets/variables.scss';
|
||||
|
||||
.md-dialog {
|
||||
min-width: 280px;
|
||||
max-width: 80%;
|
||||
max-height: 80%;
|
||||
overflow: hidden;
|
||||
.md-dialog-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 110;
|
||||
outline: none;
|
||||
border-radius: 2px;
|
||||
opacity: 0;
|
||||
filter: drop-shadow(0 7px 8px rgba(#000, $shadow-key-umbra-opacity))
|
||||
drop-shadow(0 12px 17px rgba(#000, $shadow-key-penumbra-opacity))
|
||||
drop-shadow(0 5px 22px rgba(#000, $shadow-ambient-shadow-opacity));
|
||||
clip-path: inset(0 7% 12% 7%);
|
||||
transform: translate3D(-50%, -60%, 0) scale(.85);
|
||||
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
opacity .3s $swift-ease-out-timing-function,
|
||||
clip-path .3s .1s $swift-ease-out-timing-function;
|
||||
transition-delay: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 108;
|
||||
|
||||
&.md-active {
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
clip-path: inset(-22px -22px -22px -22px);
|
||||
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
opacity .5s $swift-ease-out-timing-function,
|
||||
clip-path .4s .1s $swift-ease-out-timing-function;
|
||||
transition-delay: 0;
|
||||
transform: translate3D(-50%, -50%, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.md-dialog-container {
|
||||
padding: 24px;
|
||||
.md-dialog {
|
||||
opacity: 1 !important;
|
||||
transform: scale(1) !important;
|
||||
transition: $swift-ease-out;
|
||||
transform-property: opacity, transform;
|
||||
|
||||
> * {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.md-dialog-backdrop {
|
||||
position: fixed;
|
||||
z-index: 109;
|
||||
}
|
||||
|
||||
.md-dialog {
|
||||
min-width: 280px;
|
||||
max-width: 80%;
|
||||
max-height: 80%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 110;
|
||||
outline: none;
|
||||
border-radius: 2px;
|
||||
opacity: 0;
|
||||
box-shadow: $material-shadow-14dp;
|
||||
transform: scale(.9, .85);
|
||||
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
transform $swift-ease-out-duration .05s $swift-ease-out-timing-function;
|
||||
will-change: opacity, transform;
|
||||
|
||||
&.md-transition-off {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
> * {
|
||||
opacity: 0;
|
||||
transition: $swift-ease-out;
|
||||
transition-property: opacity;
|
||||
transition-delay: .1s;
|
||||
will-change: opacity;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<div class="md-dialog" tabindex="0">
|
||||
<div class="md-dialog-container">
|
||||
<div class="md-dialog-container" :class="classes" @keyup.esc="mdEscToClose && close()" tabindex="0">
|
||||
<div class="md-dialog" ref="dialog" :style="styles" :class="dialogClasses">
|
||||
<slot></slot>
|
||||
|
||||
<md-backdrop class="md-dialog-backdrop" ref="backdrop" @close="close"></md-backdrop>
|
||||
</div>
|
||||
|
||||
<md-backdrop class="md-dialog-backdrop" :class="classes" v-if="mdBackdrop" ref="backdrop" @close="mdClickOutsideToClose && close()"></md-backdrop>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -14,31 +14,99 @@
|
|||
import transitionEndEventName from '../../core/utils/transitionEndEventName';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
mdClickOutsideToClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
mdEscToClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
mdBackdrop: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
mdOpenFrom: String,
|
||||
mdCloseTo: String,
|
||||
mdFullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
active: false
|
||||
active: false,
|
||||
transitionOff: false,
|
||||
dialogTransform: '',
|
||||
dialogTransformOrigin: ''
|
||||
}),
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-fullscreen': this.mdFullscreen,
|
||||
'md-active': this.active
|
||||
};
|
||||
},
|
||||
dialogClasses() {
|
||||
return {
|
||||
'md-transition-off': this.transitionOff
|
||||
};
|
||||
},
|
||||
styles() {
|
||||
return {
|
||||
transform: this.dialogTransform,
|
||||
'transform-origin': this.dialogTransformOrigin
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.close();
|
||||
this.$root.$el.appendChild(this.dialogElement);
|
||||
this.$root.$el.appendChild(this.backdropElement);
|
||||
removeDialog() {
|
||||
this.$el.parentNode.removeChild(this.$el);
|
||||
},
|
||||
calculateDialogPos(ref) {
|
||||
const reference = document.querySelector(ref);
|
||||
|
||||
getComputedStyle(this.dialogElement).opacity;
|
||||
this.dialogElement.focus();
|
||||
this.dialogElement.classList.add('md-active');
|
||||
this.backdropElement.classList.add('md-active');
|
||||
if (reference) {
|
||||
const openFromRect = reference.getBoundingClientRect();
|
||||
const dialogRect = this.dialogInnerElement.getBoundingClientRect();
|
||||
const topDistance = dialogRect.top - openFromRect.top;
|
||||
const leftDistance = dialogRect.left - openFromRect.left;
|
||||
const widthInScale = openFromRect.width / dialogRect.width;
|
||||
const heightInScale = openFromRect.height / dialogRect.height;
|
||||
|
||||
this.dialogTransform = `translate3D(-${leftDistance}px, -${topDistance}px, 0) scale(${widthInScale}, ${heightInScale})`;
|
||||
this.dialogTransformOrigin = 'top left';
|
||||
}
|
||||
},
|
||||
open() {
|
||||
this.$root.$el.appendChild(this.dialogElement);
|
||||
this.transitionOff = true;
|
||||
this.calculateDialogPos(this.mdOpenFrom);
|
||||
|
||||
window.setTimeout(() => {
|
||||
this.dialogElement.focus();
|
||||
this.transitionOff = false;
|
||||
this.active = true;
|
||||
});
|
||||
},
|
||||
close() {
|
||||
if (this.$root.$el.contains(this.dialogElement)) {
|
||||
let cleanElement = () => {
|
||||
this.dialogElement.removeEventListener(transitionEndEventName, close);
|
||||
this.dialogInnerElement.removeEventListener(transitionEndEventName, cleanElement);
|
||||
this.$root.$el.removeChild(this.dialogElement);
|
||||
this.$root.$el.removeChild(this.backdropElement);
|
||||
|
||||
this.dialogTransform = '';
|
||||
this.dialogTransformOrigin = '';
|
||||
};
|
||||
|
||||
this.dialogElement.classList.remove('md-active');
|
||||
this.backdropElement.classList.remove('md-active');
|
||||
this.dialogElement.addEventListener(cleanElement, close);
|
||||
this.dialogTransform = '';
|
||||
this.dialogTransformOrigin = '';
|
||||
this.calculateDialogPos(this.mdCloseTo);
|
||||
|
||||
window.setTimeout(() => {
|
||||
this.active = false;
|
||||
this.dialogInnerElement.addEventListener(transitionEndEventName, cleanElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -46,10 +114,12 @@
|
|||
this.$nextTick(() => {
|
||||
this.rootElement = this.$root.$el;
|
||||
this.dialogElement = this.$el;
|
||||
this.backdropElement = this.$refs.backdrop.$el;
|
||||
this.$el.parentNode.removeChild(this.$el);
|
||||
this.$el.removeChild(this.$refs.backdrop.$el);
|
||||
this.dialogInnerElement = this.$refs.dialog;
|
||||
this.removeDialog();
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.removeDialog();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue