Skip to content

Commit

Permalink
feat(morph): add morph function and directive for DOM elements/compon…
Browse files Browse the repository at this point in the history
  • Loading branch information
pdanpdan committed Jul 22, 2020
1 parent a2464d6 commit e6dbbba
Show file tree
Hide file tree
Showing 26 changed files with 2,959 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/src/assets/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,10 @@ const directives = [
name: 'Mutation',
path: 'mutation'
},
{
name: 'Morph',
path: 'morph'
},
{
name: 'Scroll',
path: 'scroll'
Expand Down
68 changes: 68 additions & 0 deletions docs/src/examples/DomMorph/FabCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<div class="q-pa-md relative-position" style="min-height: 300px">
<div class="absolute-bottom-right q-ma-lg">
<div ref="refFab" class="absolute-center bg-accent" style="border-radius: 50%; width: 50%; height: 50%" />

<q-fab
direction="up"
icon="add"
color="accent"
@input="val => val === true && morph(false)"
>
<q-fab-action color="primary" @click="morph(true)" icon="alarm" />
</q-fab>
</div>

<q-card
v-if="toggle"
ref="refCard"
class="my-card text-white absolute-center bg-grey-10"
@click="morph(false)"
>
<q-card-section>
<div class="text-h6">Our Changing Planet</div>
<div class="text-subtitle2">by John Doe</div>
</q-card-section>

<q-card-section class="q-pt-none">
{{ lorem }}
</q-card-section>
</q-card>
</div>
</template>

<script>
import { dom } from 'quasar'
const { morph } = dom
export default {
data () {
return {
toggle: false,
lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
}
},
methods: {
morph (state) {
if (state !== this.toggle) {
const getFab = () => this.$refs.refFab
const getCard = () => this.$refs.refCard ? this.$refs.refCard.$el : void 0
morph(
{
from: this.toggle === true ? getCard : getFab,
to: this.toggle === true ? getFab : getCard
},
() => {
this.toggle = state
},
500
)
}
}
}
}
</script>
162 changes: 162 additions & 0 deletions docs/src/examples/DomMorph/ImageGallery.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<template>
<div class="q-pa-md">
<div
class="fixed-full image-gallery__blinder bg-orange"
:class="indexZoomed !== void 0 ? 'image-gallery__blinder--active' : void 0"
@click="zoomImage()"
/>

<div
class="row justify-center q-gutter-sm q-mx-auto scroll relative-position"
style="max-width: 80vw; max-height: 80vh; z-index: 1"
>
<q-img
v-for="(src, index) in images"
:key="index"
ref="refThumb"
class="image-gallery__image"
:style="index === indexZoomed ? 'opacity: 0.3' : void 0"
:src="src"
@click="zoomImage(index)"
/>
</div>

<q-img
ref="refFull"
class="image-gallery__image image-gallery__image-full fixed-center"
:class="indexZoomed !== void 0 ? 'image-gallery__image-full--active' : void 0"
:src="images[indexZoomed]"
@load="imgLoadedResolve"
@error="imgLoadedReject"
@click="zoomImage()"
/>
</div>
</template>

<style lang="sass">
.image-gallery
&__image
border-radius: 3%/5%
width: 150px
max-width: 20vw
cursor: pointer
z-index: 2
&-full
width: 800px
max-width: 70vw
z-index: 1000
pointer-events: none
&--active
pointer-events: all
&__blinder
opacity: 0
z-index: 0
pointer-events: none
transition: opacity 0.3s ease-in-out
&--active
opacity: 0.2
pointer-events: all
</style>

<script>
import { dom } from 'quasar'
const { morph } = dom
export default {
data () {
return {
indexZoomed: void 0,
imgLoaded: {
promise: Promise.resolve(),
resolve: () => {},
reject: () => {}
},
images: Array(24).fill(null).map((_, i) => 'https://picsum.photos/id/' + i + '/500/300')
}
},
methods: {
imgLoadedResolve () {
this.imgLoaded.resolve()
},
imgLoadedReject () {
this.imgLoaded.reject()
},
zoomImage (index) {
const { indexZoomed } = this
this.imgLoaded.reject()
const zoom = () => {
if (index !== void 0 && index !== indexZoomed) {
this.imgLoaded.promise = new Promise((resolve, reject) => {
this.imgLoaded.resolve = () => {
this.imgLoaded.resolve = () => {}
this.imgLoaded.reject = () => {}
resolve()
}
this.imgLoaded.reject = () => {
this.imgLoaded.resolve = () => {}
this.imgLoaded.reject = () => {}
reject()
}
})
this.cancel = morph(
{
from: this.$refs.refThumb[index].$el,
to: this.$refs.refFull.$el
},
() => {
this.indexZoomed = index
},
{
waitFor: this.imgLoaded.promise,
duration: 400,
hideFromClone: true,
style: 'z-index: 1',
onReady: end => {
if (end === 'from' && this.indexZoomed === index) {
this.indexZoomed = void 0
}
}
}
)
}
}
if (
indexZoomed !== void 0 &&
(this.cancel === void 0 || this.cancel() === false)
) {
morph(
{
from: this.$refs.refFull.$el,
to: this.$refs.refThumb[indexZoomed].$el
},
() => {
this.indexZoomed = void 0
},
{
duration: 200,
keepToClone: true,
style: 'z-index: 1',
onReady: zoom
}
)
}
else {
zoom()
}
}
}
}
</script>
73 changes: 73 additions & 0 deletions docs/src/examples/DomMorph/ImageStripHorizontal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<div class="q-pa-md">
<div class="row no-wrap q-gutter-x-sm" style="overflow-x: auto; overflow-y: visible;">
<q-img
v-for="(src, index) in images"
:key="index"
ref="refThumb"
class="cursor-pointer"
:class="index === indexZoomed ? 'fixed-top q-mt-md q-mx-auto z-top' : void 0"
style="border-radius: 3%/5%; flex: 0 0 10vw"
:style="index === indexZoomed ? 'width: 800px; max-width: 70vw' : void 0"
:src="src"
@click="zoomImage(index)"
/>
</div>
</div>
</template>

<script>
import { dom } from 'quasar'
const { morph } = dom
export default {
data () {
return {
indexZoomed: void 0,
images: Array(24).fill(null).map((_, i) => 'https://picsum.photos/id/' + i + '/500/300')
}
},
methods: {
zoomImage (index) {
const { indexZoomed } = this
this.indexZoomed = void 0
if (index !== void 0 && index !== indexZoomed) {
this.cancel = morph(
this.$refs.refThumb[index].$el,
() => {
this.indexZoomed = index
},
{
duration: 500,
style: 'z-index: 1',
onReady: end => {
if (end === 'from' && this.indexZoomed === index) {
this.indexZoomed = void 0
}
}
}
)
}
if (
indexZoomed !== void 0 &&
(this.cancel === void 0 || this.cancel() === false)
) {
morph(
this.$refs.refThumb[indexZoomed].$el,
void 0,
{
waitFor: 100,
duration: 300,
style: 'z-index: 1'
}
)
}
}
}
}
</script>
73 changes: 73 additions & 0 deletions docs/src/examples/DomMorph/ImageStripVertical.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<div class="q-pa-md">
<div class="q-gutter-y-sm" style="overflow-x: visible; overflow-y: auto; width: 300px; max-width: 20vw; max-height: 80vh">
<q-img
v-for="(src, index) in images"
:key="index"
ref="refThumb"
class="cursor-pointer"
:class="index === indexZoomed ? 'fixed-top-right q-mr-md q-mt-md z-top' : void 0"
style="border-radius: 3%/5%;"
:style="index === indexZoomed ? 'width: 800px; max-width: 70vw;' : void 0"
:src="src"
@click="zoomImage(index)"
/>
</div>
</div>
</template>

<script>
import { dom } from 'quasar'
const { morph } = dom
export default {
data () {
return {
indexZoomed: void 0,
images: Array(24).fill(null).map((_, i) => 'https://picsum.photos/id/' + i + '/500/300')
}
},
methods: {
zoomImage (index) {
const { indexZoomed } = this
this.indexZoomed = void 0
if (index !== void 0 && index !== indexZoomed) {
this.cancel = morph(
this.$refs.refThumb[index].$el,
() => {
this.indexZoomed = index
},
{
duration: 500,
style: 'z-index: 1',
onReady: end => {
if (end === 'from' && this.indexZoomed === index) {
this.indexZoomed = void 0
}
}
}
)
}
if (
indexZoomed !== void 0 &&
(this.cancel === void 0 || this.cancel() === false)
) {
morph(
this.$refs.refThumb[indexZoomed].$el,
void 0,
{
waitFor: 100,
duration: 300,
style: 'z-index: 1'
}
)
}
}
}
}
</script>
Loading

0 comments on commit e6dbbba

Please sign in to comment.