An Image-Carousel, for carouselling images, ya know.
|
<div id="app"> |
|
<image-carousel :source="carouselSource"> |
|
<i class="of-course">Yes, I've created this Image Carousel! <i class="fa fa-smile"></i></i> |
|
</image-carousel> |
|
</div> |
|
//Assign a data source like so: |
|
const carouselSource = [ |
|
{img: 'img-a.png', title: 'img-a'}, |
|
{img: 'img-b.png', title: 'img-b'}, |
|
{img: 'img-c.png', title: 'img-c'}, |
|
]; |
|
|
|
new Vue({ |
|
el: '#app', |
|
data: { |
|
carouselSource: carouselSource |
|
} |
|
}); |
|
Vue.component('image-carousel', { |
|
props: ['source'], |
|
|
|
data() { |
|
return { |
|
currentIndex: 0 |
|
}; |
|
}, |
|
|
|
computed: { |
|
currentSource() { |
|
return this.source[this.currentIndex]; |
|
} |
|
}, |
|
|
|
methods: { |
|
offset(amount) { |
|
var index = this.currentIndex; |
|
var s = this.source; |
|
index += amount; |
|
|
|
while(index<0) index += s.length; |
|
while(index>=s.length) index -= s.length; |
|
|
|
if(this.currentIndex==index) return; |
|
this.currentIndex = index; |
|
this.flickerImg(); |
|
}, |
|
|
|
getFACircle(id) { |
|
return (this.currentIndex==id ? 'selected' : '') + ' fa fa-circle'; |
|
}, |
|
|
|
onCircleClick(id) { |
|
if(this.currentIndex===id) return; |
|
this.currentIndex = id; |
|
this.flickerImg(); |
|
clearInterval( this._autoSlide ); |
|
}, |
|
|
|
onNavClick(id) { |
|
this.offset(id); |
|
clearInterval( this._autoSlide ); |
|
}, |
|
|
|
flickerImg() { |
|
var img = this.$refs.img; |
|
|
|
if(this._twn) { |
|
this._twn.kill(); |
|
this._twn = null; |
|
} |
|
|
|
this._twn = TweenMax.fromTo(img, 0.4, {alpha:0}, {alpha:1}); |
|
} |
|
}, |
|
|
|
mounted() { |
|
this._autoSlide = setInterval(() => { |
|
this.offset(1); |
|
}, 3000); |
|
}, |
|
|
|
template: `<i class="image-carousel"> |
|
<i class="image-container"> |
|
<img ref="img" :src="currentSource.img" :alt="currentSource.title" :title="currentSource.title" @click="onNavClick(0)"></img> |
|
<i class="nav prev fa fa-chevron-left" @click="onNavClick(-1)"></i> |
|
<i class="nav next fa fa-chevron-right" @click="onNavClick(1)"></i> |
|
</i> |
|
<div class="image-controls"> |
|
<i :class="getFACircle(s)" v-for="(src, s) in source" @click="onCircleClick(s)"> |
|
<img :src="src.img" class="hidden preload"></img> |
|
</i> |
|
</div> |
|
<slot></slot> |
|
</i>` |
|
}); |
|
.promo { |
|
display: block; |
|
position: relative; |
|
padding: 20px 0px; |
|
background: linear-gradient(to bottom, #333, #666, #333); |
|
} |
|
|
|
.image-carousel { |
|
text-align: center; |
|
position: relative; |
|
display: block; |
|
width: 100%; |
|
} |
|
|
|
.image-container { |
|
position: relative; |
|
display: inline-block; |
|
width: 625px; |
|
height: 315px; |
|
box-shadow: 0 0 32px #00000088; |
|
} |
|
|
|
.image-container .nav { |
|
top: 50%; |
|
left: 0px; |
|
padding: 50px 20px; |
|
margin-top: -50px; |
|
color: #fff; |
|
position: absolute; |
|
display: inline-block; |
|
background: #000000aa; |
|
opacity: 0; |
|
transition: opacity 0.3s; |
|
cursor: pointer; |
|
box-shadow: 0 0 32px #000000aa; |
|
} |
|
|
|
.image-container:hover .nav { |
|
opacity: 1; |
|
} |
|
|
|
.image-container .next { |
|
left: auto; |
|
right: 0px; |
|
} |
|
|
|
.hidden { |
|
display: none; |
|
} |
|
|
|
.image-controls { |
|
display: block; |
|
padding-top: 15px; |
|
} |
|
|
|
.image-controls i { |
|
padding: 6px 4px; |
|
color: #888; |
|
transition: text-shadow 0.3s; |
|
} |
|
|
|
.image-controls i.selected { |
|
color: #ccc; |
|
text-shadow: 0 0 2px #000, 0 0 8px #fff; |
|
} |
|
|
|
.promo .of-course { |
|
position: absolute; |
|
right: 25px; |
|
bottom: 0px; |
|
} |
|
|
|
.of-course { |
|
display: inline-block; |
|
color: #444; |
|
font-style: italic; |
|
transition: text-shadow 0.4s, color 0.4s; |
|
} |
|
|
|
.of-course a { |
|
color: inherit; |
|
text-decoration: none; |
|
} |