28 |
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 | 
7 | ## With auto sliding and progressbar
8 | 
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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
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 |