├── Carousel.vue ├── LICENSE ├── README.md ├── carousel.css ├── carousel.js ├── component.html ├── images ├── p1.jpeg ├── p2.jpeg ├── p3.jpeg ├── p4.jpeg ├── puff.svg └── thumbs │ ├── p1.jpeg │ ├── p2.jpeg │ ├── p3.jpeg │ └── p4.jpeg └── index.html /Carousel.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 141 | 142 | 143 | 229 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue carousel 2 | ## Simple vue component that outputs an infinite carousel 3 | ### built with [Vue.js](https://vuejs.org/ "Vue's Homepage") and [Bulma](https://bulma.io/ "Bulma's Homepage") 4 | # Preview 5 | ## Simple 6 | ![vue carousel](https://i.imgur.com/SPB4hcL.gif "Vue carousel in action") 7 | ## With auto sliding and progressbar 8 | ![vue carousel auto slide](https://i.imgur.com/shuNL8Z.gif "Vue carousel with auto slide") 9 | # Props 10 | 1. **images** (required): Accepts array of objects. 11 | 2. **starting-image** (optional) [DEFAULT: 0]: Accepts the index of the image that the carousel starts from 12 | 3. **auto-slide-interval** (optional): time in milliseconds to auto slide to the next image e.g. 1000, which is 1 second 13 | 4. **show-progress-bar** (optional) [DEFAULT: false]: boolean to show or hide the progressbar on top of the images. Needs to be used with **auto-slide-interval** prop. 14 | ```javascript 15 | //Example of images 16 | let images = [ 17 | { 18 | id: '1', 19 | big: 'path to full image', 20 | thumb: 'path to thumbnail' 21 | }, 22 | { 23 | id: '2', 24 | big: 'path to full image', 25 | thumb: 'path to thumbnail' 26 | } 27 | ] 28 | ``` 29 | 30 | ## Example usage 31 | ## Method 1 32 | You can see an example in both index.html and component.html 33 | ### Steps 34 | 1. include vue.js 35 | 2. include the carousel.js 36 | 3. create the images array 37 | 4. reference the carousel in your html 38 | 39 | ## Method 2 40 | Using the component with vue cli as a single file component 41 | 42 | > This method does **not** use Bulma 43 | ### Note 44 | To reference the Carousel with another name 45 | - change the name of the file (Carousel.vue) to whatever you want e.g. **MyCarousel.vue** 46 | - change the `name` attribute inside the file to the previously given name e.g. **MyCarousel** 47 | ### Steps 48 | 1. Download Carousel.vue 49 | 2. Copy the file to your project 50 | 3. create the images array 51 | 4. ```javascript 52 | // import the Carousel.vue 53 | import Carousel from 'path/to/Carousel.vue' 54 | 64 | ``` 65 | 5. reference it in your template as shown in the examples below 66 | 67 | ```html 68 | 69 | 73 | ``` 74 | ```html 75 | 76 | 81 | ``` 82 | ```html 83 | 84 | 90 | ``` 91 | 92 | You can also find a post I've written explaining the process on [dev.to](https://dev.to/tsanak/building-an-image-carousel-with-vuejs--cjp "Vue carousel post") 93 | 94 | ## :memo: Features 95 | If you want a new feature to be implemented you can create an issue with the label Feature. 96 | 97 | ## Contributing 98 | Pull requests are more than welcome! :smiley: -------------------------------------------------------------------------------- /carousel.css: -------------------------------------------------------------------------------- 1 | .card-carousel { 2 | user-select: none; 3 | position: relative; 4 | } 5 | 6 | .progressbar { 7 | display: block; 8 | width: 100%; 9 | height: 5px; 10 | position: absolute; 11 | background-color: rgba(221, 221, 221, 0.25); 12 | z-index: 1; 13 | } 14 | 15 | .progressbar > div { 16 | background-color: rgba(255, 255, 255, 0.52); 17 | height: 100%; 18 | } 19 | 20 | .thumbnails { 21 | display: flex; 22 | justify-content: space-evenly; 23 | flex-direction: row; 24 | } 25 | 26 | .thumbnail-image { 27 | display: flex; 28 | align-items: center; 29 | cursor: pointer; 30 | padding: 2px; 31 | } 32 | 33 | .thumbnail-image > img { 34 | width: 100%; 35 | height: auto; 36 | transition: all 250ms; 37 | } 38 | 39 | .thumbnail-image:hover > img, 40 | .thumbnail-image.active > img { 41 | opacity: 0.6; 42 | box-shadow: 2px 2px 6px 1px rgba(0,0,0, 0.5); 43 | } 44 | 45 | .card-img { 46 | position: relative; 47 | margin-bottom: 15px; 48 | } 49 | 50 | .card-img > img { 51 | display: block; 52 | margin: 0 auto; 53 | } 54 | 55 | .actions { 56 | font-size: 1.5em; 57 | height: 40px; 58 | position: absolute; 59 | top: 50%; 60 | margin-top: -20px; 61 | width: 100%; 62 | display: flex; 63 | align-items: center; 64 | justify-content: space-between; 65 | color: #585858; 66 | } 67 | 68 | .actions > span { 69 | cursor: pointer; 70 | transition: all 250ms; 71 | } 72 | 73 | .actions > span.prev { 74 | margin-left: 5px; 75 | } 76 | 77 | .actions > span.next { 78 | margin-right: 5px; 79 | } 80 | 81 | .actions > span:hover { 82 | color: #eee; 83 | } -------------------------------------------------------------------------------- /carousel.js: -------------------------------------------------------------------------------- 1 | Vue.component('carousel', { 2 | template: ` 3 | 29 | `, 30 | computed: { 31 | // currentImage gets called whenever activeImage changes 32 | // and is the reason why we don't have to worry about the 33 | // big image getting updated 34 | currentImage() { 35 | this.timeLeft = this.autoSlideInterval; 36 | return this.images[this.activeImage].big; 37 | }, 38 | progressBar() { 39 | //Calculate the width of the progressbar 40 | return 100 - (this.timeLeft/this.autoSlideInterval) * 100; 41 | } 42 | }, 43 | data() { 44 | return { 45 | //Index of the active image 46 | activeImage: 0, 47 | //Hold the timeout, so we can clear it when it is needed 48 | autoSlideTimeout: null, 49 | //If the timer is stopped e.g. when hovering over the carousel 50 | stopSlider: false, 51 | //Hold the time left until changing to the next image 52 | timeLeft: 0, 53 | //Hold the interval so we can clear it when needed 54 | timerInterval: null, 55 | //Every 10ms decrease the timeLeft 56 | countdownInterval: 10 57 | } 58 | }, 59 | methods: { 60 | // Go forward on the images array 61 | // or go at the first image if you can't go forward 62 | nextImage() { 63 | var active = this.activeImage + 1; 64 | if(active >= this.images.length) { 65 | active = 0; 66 | } 67 | this.activateImage(active); 68 | }, 69 | // Go backwards on the images array 70 | // or go at the last image 71 | prevImage() { 72 | var active = this.activeImage - 1; 73 | if(active < 0) { 74 | active = this.images.length - 1; 75 | } 76 | this.activateImage(active); 77 | }, 78 | activateImage(imageIndex) { 79 | this.activeImage = imageIndex; 80 | }, 81 | //Wait until 'interval' and go to the next image; 82 | startTimer(interval) { 83 | if(interval && interval > 0 && !this.stopSlider) { 84 | var self = this; 85 | clearTimeout(this.autoSlideTimeout); 86 | this.autoSlideTimeout = setTimeout(function() { 87 | self.nextImage(); 88 | self.startTimer(self.autoSlideInterval); 89 | }, interval); 90 | } 91 | }, 92 | //Stop the timer when hovering over the carousel 93 | stopTimer() { 94 | clearTimeout(this.autoSlideTimeout); 95 | this.stopSlider = true; 96 | clearInterval(this.timerInterval); 97 | }, 98 | //Restart the timer(with 'timeLeft') when leaving from the carousel 99 | restartTimer() { 100 | this.stopSlider = false; 101 | clearInterval(this.timerInterval); 102 | this.startCountdown(); 103 | this.startTimer(this.timeLeft); 104 | }, 105 | //Start countdown from 'autoSlideInterval' to 0 106 | startCountdown() { 107 | if(!this.showProgressBar) return; 108 | var self = this; 109 | this.timerInterval = setInterval(function() { 110 | self.timeLeft -= self.countdownInterval; 111 | if(self.timeLeft <= 0) { 112 | self.timeLeft = self.autoSlideInterval; 113 | } 114 | }, this.countdownInterval); 115 | } 116 | }, 117 | created() { 118 | //Check if startingImage prop was given and if the index is inside the images array bounds 119 | if(this.startingImage 120 | && this.startingImage >= 0 121 | && this.startingImage < this.images.length) { 122 | this.activeImage = this.startingImage; 123 | } 124 | 125 | //Check if autoSlideInterval prop was given and if it is a positive number 126 | if(this.autoSlideInterval 127 | && this.autoSlideInterval > this.countdownInterval) { 128 | //Start the timer to go to the next image 129 | this.startTimer(this.autoSlideInterval); 130 | this.timeLeft = this.autoSlideInterval; 131 | //Start countdown to show the progressbar 132 | this.startCountdown(); 133 | } 134 | }, 135 | props: ['startingImage', 'images', 'autoSlideInterval', 'showProgressBar'] 136 | }) -------------------------------------------------------------------------------- /component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vue slider 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 | 23 |

They are taking

24 |
25 |
26 |
27 |
28 |
29 |
30 | 34 |

the hobbits

35 |
36 |
37 |
38 |
39 |
40 |
41 | 45 |

to Isengard

46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 | 54 | 86 | 87 | -------------------------------------------------------------------------------- /images/p1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/p1.jpeg -------------------------------------------------------------------------------- /images/p2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/p2.jpeg -------------------------------------------------------------------------------- /images/p3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/p3.jpeg -------------------------------------------------------------------------------- /images/p4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/p4.jpeg -------------------------------------------------------------------------------- /images/puff.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 28 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /images/thumbs/p1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/thumbs/p1.jpeg -------------------------------------------------------------------------------- /images/thumbs/p2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/thumbs/p2.jpeg -------------------------------------------------------------------------------- /images/thumbs/p3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/thumbs/p3.jpeg -------------------------------------------------------------------------------- /images/thumbs/p4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsanak/vue-carousel/93534d2b8245e1de1126fcadbc181f8f14860df5/images/thumbs/p4.jpeg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vue slider 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 | 40 |

Oh hi there

41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 106 | 107 | --------------------------------------------------------------------------------