add GalleryMap component in Gallery

This commit is contained in:
axolotle
2021-07-09 11:19:40 +02:00
parent 5343caa4a6
commit af1dc1320c
5 changed files with 170 additions and 9 deletions
+4 -4
View File
@@ -7,11 +7,11 @@
:body-class="{ paddings: !noCross }" :body-class="{ paddings: !noCross }"
backdrop backdrop-variant="light" backdrop backdrop-variant="light"
> >
<template #default="{ hide }"> <template #default="{ hide, visible }">
<div v-if="!noCross" class="btn-close-wrapper"> <div v-if="!noCross" class="btn-close-wrapper">
<button-close @click="hide()" /> <button-close @click="hide()" />
</div> </div>
<slot name="default" v-bind="{ hide }" /> <slot name="default" v-bind="{ hide, visible }" />
</template> </template>
</b-sidebar> </b-sidebar>
</template> </template>
@@ -38,11 +38,11 @@ export default {
background-color: red; background-color: red;
width: auto; width: auto;
@include media-breakpoint-down($size-bp-down) { @media (orientation: portrait) {
width: 100%; width: 100%;
} }
@include media-breakpoint-up($size-bp) { @media (orientation: landscape) {
max-width: 50%; max-width: 50%;
&:not(.b-sidebar-right) { &:not(.b-sidebar-right) {
+20 -4
View File
@@ -1,11 +1,18 @@
<template> <template>
<div class="gallery"> <div class="gallery">
<b-button v-b-toggle.gallery-map variant="creation" class="btn-side left"> <b-button v-b-toggle.gallery-map-side variant="creation" class="btn-side left">
{{ $t('map') }} {{ $t('map') }}
</b-button> </b-button>
<side-view id="gallery-map"> <side-view id="gallery-map-side">
MAP <template #default="{ hide, visible }">
<gallery-map
v-if="creations"
:nodes="creations" :node="creation"
:visible="visible"
@open-creation="openCreation($event, hide)"
/>
</template>
</side-view> </side-view>
<gallery-view <gallery-view
@@ -47,7 +54,7 @@ import { mapGetters } from 'vuex'
import { getRelation } from '@/store/utils' import { getRelation } from '@/store/utils'
import { SideView } from '@/components/layouts' import { SideView } from '@/components/layouts'
import { NodeViewTitle } from '@/components/nodes' import { NodeViewTitle } from '@/components/nodes'
import { GalleryView } from '@/pages/gallery' import { GalleryView, GalleryMap } from '@/pages/gallery'
export default { export default {
@@ -56,6 +63,7 @@ export default {
components: { components: {
SideView, SideView,
GalleryView, GalleryView,
GalleryMap,
NodeViewTitle NodeViewTitle
}, },
@@ -138,6 +146,14 @@ export default {
} }
} }
::v-deep #gallery-map-side {
width: 100%;
.btn-close {
float: unset;
}
}
#gallery-index { #gallery-index {
ul { ul {
padding: 0; padding: 0;
+141
View File
@@ -0,0 +1,141 @@
<template>
<div class="gallery-map wh-100">
<div class="gallery-map-wrapper" :style="`--max: ${max}px;`">
<div class="rows" v-if="dots && max">
<div
v-for="(row, y) in dots" :key="y"
class="row"
:class="{ sub: y % 2 === 0 }"
>
<div
v-for="(dot, x) in row" :key="`${y}-${x}`"
class="dot" :class="{ current: dot === node }"
>
<img
v-if="dot"
:src="dot.image.url"
:alt="dot.image.alt"
@click="$emit('open-creation', dot.id)"
>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { shuffle } from '@/helpers/common'
export default {
name: 'GalleryMap',
props: {
nodes: { type: Array, required: true },
node: { type: Object, required: true },
visible: { type: Boolean, required: true }
},
data () {
return {
dots: undefined,
size: [0, 0],
max: undefined
}
},
watch: {
visible (visible) {
if (visible) {
this.defineSize()
}
}
},
methods: {
setDots () {
const nodesLen = this.nodes.length
const sqrt = Math.ceil(Math.sqrt(nodesLen))
const rows = Math.floor(Math.sqrt(Math.pow(sqrt, 2) / 2))
const len = rows + 1
let max = rows * len * 2
let extra = 0
while (max - nodesLen < 0) {
extra += 1
max += extra % 2 === 0 ? rows : len
}
const nodes = shuffle([...this.nodes, ...Array(max - nodesLen).fill(undefined)])
const dots = []
for (var y = 0; y < len + rows + extra; y++) {
const x = y % 2 === 0 ? rows : len
dots.push(nodes.splice(0, x))
}
this.size = [len, len + rows + extra]
this.dots = dots
},
defineSize () {
const [x, y] = this.size
const { offsetWidth, offsetHeight } = document.querySelector('.gallery-map-wrapper')
const h = offsetHeight / (y * 2 - 1)
const w = offsetWidth / (x * 2 - 1)
this.max = Math.min(Math.min(h, w), 100)
}
},
created () {
this.setDots()
}
}
</script>
<style lang="scss" scoped>
.gallery-map {
&-wrapper {
width: 100%;
position: relative;
height: 100%;
}
.rows {
position: absolute;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
height: 100%;
width: 100%;
}
.row {
display: flex;
justify-content: space-between;
width: 100%;
&.sub {
justify-content: space-around;
}
}
.dot {
display: flex;
width: var(--max);
height: var(--max);
img {
max-width: 100%;
max-height: 100%;
margin: auto;
cursor: pointer;
}
&.current {
border: 5px solid theme-color('creation');
background-color: theme-color('creation');
}
}
}
</style>
+4 -1
View File
@@ -159,8 +159,11 @@ export default {
&-caption { &-caption {
height: 100%; height: 100%;
text-align: center; text-align: center;
font-size: 1.15rem;
font-family: $font-family-text; font-family: $font-family-text;
@include media-breakpoint-up($size-bp) {
font-size: 1.5rem;
}
} }
.gallery-view-btn-wrapper { .gallery-view-btn-wrapper {
+1
View File
@@ -1 +1,2 @@
export { default as GalleryView } from './GalleryView' export { default as GalleryView } from './GalleryView'
export { default as GalleryMap } from './GalleryMap'