Skip to content

Instantly share code, notes, and snippets.

@Jorybraun
Created June 23, 2018 08:48
Show Gist options
  • Save Jorybraun/e8781246b143be0e45e30ea3923ed1ae to your computer and use it in GitHub Desktop.
Save Jorybraun/e8781246b143be0e45e30ea3923ed1ae to your computer and use it in GitHub Desktop.
carousel with blinds
<template>
<div class='carousel'>
<svg width="100%" viewBox="0 0 100vw 100vh">
<transition-group tag='g'
appear
appear-class="reveal"
ref='svg'
name='blinds'
@after-enter='afterEnter'
@after-leave='afterLeave'>
<template v-if="showBlinds">
<rect v-for='i in blindsCount'
height='100%'
:key='i'
:x="`${(width / blindsCount) * (i - 1)}px`"
:width="`${(width / blindsCount)}px`"></rect>
</template>
</transition-group>
</svg>
<picture>
<img :src='images[currentImage]' />
</picture>
</div>
</template>
<script>
import ResizeObserver from "resize-observer-polyfill";
export default {
name: "AcneCarousel",
props: {
images: {
type: Array,
default: () => []
},
maxBlindWidth: {
type: Number | String,
default: 24
}
},
data() {
return {
currentImage: 0,
showBlinds: true,
offsetWidth: 0,
width: 0,
resizeObserver: false
};
},
methods: {
next() {
if (this.currentImage === this.images.length - 1) {
this.currentImage = 0;
} else {
this.currentImage = this.currentImage + 1;
}
this.showBlinds = true;
},
afterEnter() {
setTimeout(() => {
this.showBlinds = false;
}, 4800)
},
afterLeave(e) {
if(!this.showBlinds) {
this.next()
}
}
},
computed: {
blindsCount() {
return Math.floor(this.width / this.maxBlindWidth);
},
blindWidth() {
return Math.floor(100 / this.blindsCount);
}
},
mounted() {
this.width = this.$el.offsetWidth;
this.resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const { width } = entry.contentRect;
this.$nextTick(() => {
this.width = width;
});
}
});
this.resizeObserver.observe(this.$el);
}
};
</script>
<style scoped lang='scss'>
.carousel {
width: 100%;
height: 100%;
max-height: 100vh;
position: relative;
display: flex;
justify-content: center;
}
picture {
height: 100%;
display: flex;
justify-content: center;
z-index: -1;
}
picture img {
object-fit: contain;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
svg {
width: 100%;
height: 100%;
max-height: 100vh;
z-index: 10000;
position: absolute;
perspective: 500px;
}
svg rect {
--width: 25px;
fill: #2c82e1;
stroke: #2c82e1;
height: 100%;
transform: scale(0, 1);
transform-box: fill-box;
transform-style: preserve-3d;
transform-origin: left top;
}
svg.reveal rect {
transform: scale(1, 1) translateZ(0);
-webkit-backface-visibility: hidden;
}
.blinds-enter-active {
animation: blinds-in 2s linear ;
}
.blinds-leave-active {
animation: blinds-in 2s linear reverse;
}
@keyframes blinds-in {
0% {
transform: scale(1,1);
transform-box: fill-box;
}
100% {
transform: scale(0, 1);
transform-box: fill-box;
stroke: none;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment