📜 ⬆️ ⬇️

Own image slider on jQuery

image
To begin with, this article is written to tell you how to create an image scrolling slider for web pages. This article is by no means educational in nature; it only serves as an example of how we can realize our subject matter. You can use the code provided in this article as a kind of template for such developments, I hope that I will be able to convey to the reader in sufficient detail and with all the essence of what I have written.



And now to the point, not so long ago, I needed to put the slider on one site, but having searched the Internet for ready-made scripts, I did not find anything worthwhile, because some did not work as I needed, while others did not run at all without errors in the console. Using jQuery - plugins for the slider seemed to me too uninteresting, because I will solve the problem with this, but I will not have an understanding about the operation of this mechanism, and using the plugin for the sake of one slider is not very optimal. I also didn’t really want to understand curved scripts, that's why I decided to write my own script for the slider, which I will mark as I need.


To begin, we need to decide on the logic of the slider itself, and then proceed to implement, at this stage it is very important to have a clear understanding of the operation of this mechanism, because without it we don’t write code that works exactly as we want.


The main object we will have is the viewport , that is, the block in which we will see our pictures spinning, in it we will have a slidewrapper , this will be our block containing all the images lined up in one line and which will change its position inside the viewport itself.
image
Then, on the sides inside the viewport , vertically in the middle, there will be buttons back and forth, when clicking on them, we will also change the position of our slidewrapper relative to the viewport , thereby causing the effect of scrolling through pictures. And finally, the last object will be our navigation buttons at the bottom of the viewport .
image
When you click on them, we will simply look at the sequence number of this button and move to the slide we need again by shifting the slidewrapper (the shift will be done by changing the transform css property , the value of which will be constantly calculated).


I think that the logic of the work of this whole case should be clear after the above, but if there are any misunderstandings somewhere, then everything will become clearer in the code, you need only a little patience.


And now let's write! First, open our index file and write the markup we need there:


<div id="block-for-slider"> <div id="viewport"> <ul id="slidewrapper"> <li class="slide"><img src="img/1.jpg" alt="1" class="slide-img"></li> <li class="slide"><img src="img/2.jpg" alt="2" class="slide-img"></li> <li class="slide"><img src="img/3.jpg" alt="3" class="slide-img"></li> <li class="slide"><img src="img/4.jpg" alt="4" class="slide-img"></li> </ul> </div> </div> 

As you can see, nothing complicated, block-for-slider serves just as a block in which our slider will be placed, inside it is the viewport itself, in which our slidewrapper is located, it’s also a nested list, here li are slides, and img - pictures inside of them. I ask you to pay attention to the fact that all the pictures must be of the same size or, at least, of proportions, otherwise the slider will look crooked, because its dimensions directly depend on the proportions of the image.


Now we need to stylize the whole thing, usually the styles are not specifically commented, but I decided to focus on this so that there would be no misunderstanding in the future.


 body { margin: 0; padding: 0; } #block-for-slider { width: 800px; margin: 0 auto; margin-top: 100px; } #viewport { width: 100%; display: table; position: relative; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; } #slidewrapper { position: relative; width: calc(100% * 4); top: 0; left: 0; margin: 0; padding: 0; -webkit-transition: 1s; -o-transition: 1s; transition: 1s; -webkit-transition-timing-function: ease-in-out; -o-transition-timing-function: ease-in-out; transition-timing-function: ease-in-out; } #slidewrapper ul, #slidewrapper li { margin: 0; padding: 0; } #slidewrapper li { width: calc(100%/4); list-style: none; display: inline; float: left; } .slide-img { width: 100%; } 

Let's start with block-for-slider , this, I repeat, is our block on the page, which we will allocate under the slider, its height will depend on its width and on the proportions of our image, since viewport occupies the entire width of the block-for-slider , then the slide itself has the same width, and, accordingly, the picture inside it changes its height depending on the width (proportions are preserved). I placed this element horizontally in the middle on my page; 100px retreated from above, making its position more convenient for example.


The viewport element, as already mentioned, occupies the entire width of our block-for-slider , it has the overflow: hidden property, it will allow us to hide our image tape, which climbs beyond viewport.
image
The following css-property - user-select: none , allows you to get rid of the blue selection of individual elements of the slider with numerous clicks on the buttons.


Moving on to slidewrapper , why is position: relative , not absolute ? It's very simple, because if we choose the second option, then with the viewport overflow: hidden property, nothing will seem to us, since viewport itself will not adjust to the height of the slidewrapper , because of which it will have height: 0 . Why is width so important and why do we ask it at all? The fact is that our slides will have a width equal to 100% of the viewport , and to arrange them in line, we need a place where they will stand, so the width of the slidewrapper must be equal to 100% of the width of the viewport multiplied by the number of slides ( my case on 4). As for the transition and transition-timing-function , here 1s means that the change of position of the slidewrapper will occur within 1 second and we will observe this, and ease-in-out is a type of animation in which it first goes slowly, accelerates until the middle, and then slows down again, here you can already set the values ​​at your discretion.


The following property block sets slidewrapper and its children to zero indents, no comments here.


Next, we stylize our slides, their width should be equal to the width of the viewport , but since they are in slidewrapper , whose width is equal to the viewport width multiplied by the number of slides, then to get the viewport width again, we need to divide 100% of the width of the slidewrapper into the number of slides (in my case, again, by 4). After that, turn them into string elements using display: inline and set the flow to the left by adding the float: left property. About list-style: none, I can say that I use it to remove the default marker from li , in most cases it is a kind of standard.


Everything is simple with the slide-img , the picture will occupy the entire width of the slide , the slide will adjust to its height, the slidewrapper will adjust to the height of the slide , and the height of the viewport will in turn take on the value of the height of slidewrapper , so the height of our slider will depend on the image proportions and block sizes provided under the slider, as I have already written above.


I think on this we have figured out the styles, for the time being we will do a simple slide show without buttons, and after we make sure that it works properly, we will add and style them.


Let's open our js-file , in which the slider code will be, do not forget to connect jQuery , since we will write using this framework. I, by the way, at the time of this writing, I am using jQuery version 3.1.0 . The very file with the script must be connected at the very end of the body tag, because we will work with DOM elements that need to be initialized first.


For now, we need to declare a couple of variables, one will store the slide number we see at a certain point in time in the viewport , I called it slideNow , and the second will store the number of these slides, this is slideCount .


 var slideNow = 1; var slideCount = $('#slidewrapper').children().length); 

The slideNow variable must be set to an initial value of 1, since When we load the page, we will see the first slide in the viewport , based on our markup.


In the slideCount we put the number of child elements slidewrapper , everything is logical here.
Next, you need to create a function that is exactly the same and will be responsible for switching slides from right to left, declare it:


 function nextSlide() { } 

We will call it in the main block of our code, which we will get to, but for now let's say our function, what it needs to do:


 function nextSlide() { if (slideNow == slideCount || slideNow <= 0 || slideNow > slideCount) { $('#slidewrapper').css('transform', 'translate(0, 0)'); slideNow = 1; } else { translateWidth = -$('#viewport').width() * (slideNow); $('#slidewrapper').css({ 'transform': 'translate(' + translateWidth + 'px, 0)', '-webkit-transform': 'translate(' + translateWidth + 'px, 0)', '-ms-transform': 'translate(' + translateWidth + 'px, 0)', }); slideNow++; } } 

To begin with, we check whether we are now on the last slide of our tape? To do this, we take the number of all our slides with $ ('# slidewrapper'). Children (). Length and check it with the number of our slide, if they are equal, it means that we need to start showing the tape again, from 1 slide , which means we change the css-property transform of the slidewrapper to translate (0, 0) , thus shifting it to its original position so that the first slide is in our field of view, let's not forget also the –webkit and –ms for an adequate cross-browser display (see reference book on css-properties ). After that, let's not forget to update the value of the variable slideNow , informing it that the field of view is slide number 1: slideNow = 1;


This condition also includes checking that the number of the slide that we see is within the number of our slides, but if somehow this is not done, then we’ll go back to the 1st slide.


If the first condition is not met, then it means that at the moment we are neither on the last slide, nor on some non-existent one, which means we need to switch to the next one, we will do this by shifting the slidewrapper to the left by value, equal to the width of the viewport , the offset will again occur through the property known to us translate , whose value will be equal to 'translate (' + translateWidth + 'px, 0)' , where translateWidth is the distance that our slidewrapper is shifted. By the way, let's declare this variable at the beginning of our code:


 var translateWidth = 0; 

After moving to the next slide, let’s tell our slideNow that we see the next slide: slideNow ++;


At the moment, some readers may wonder: why don't we replace $ ('# viewport'). Width () with some variable, for example slideWidth , to always have the width of our slide on hand? The answer is very simple, if our site is adaptive, then, accordingly, the block allocated for the slider is also adaptive, so you can understand that when the window width is resized without reloading the page (for example, turning the phone on its side), the viewport width will change, and accordingly, the width of one slide will change. In this case, our slidewrapper will shift to the value of that width, which was originally, which means the pictures will be displayed in parts or not at all displayed in the viewport . Writing $ ('# viewport'). Width () to our function instead of slideWidth, we force it to calculate the viewport width each time the slides are switched, thereby providing a twist to the desired slide during a sharp change in screen width.


However, we wrote a function, now we need to call it after a certain time interval, we can also store the interval in a variable, so that if we want to change it, change only one value in the code:


 var slideInterval = 2000; 

The time in js is specified in milliseconds.


Now we will write this construction:


 $(document).ready(function () { setInterval(nextSlide, slideInterval); }); 

Everything is easier nowhere, we say through the construction of $ (document) .ready (function () {}) that the following actions must be performed after the document is fully loaded. Then we simply call the function nextSlide with an interval equal to slideInterval , using the built-in function setInterval .


After all the actions that we performed above, our slider should spin perfectly, but if something went wrong with you, then the problem may be either in the jQuery version or in the wrong connection of any files. Also, it is not necessary to exclude that you could make a mistake somewhere in the code, so I can only advise to double-check everything.
image
In the meantime, moving on, we will add to our slider a function such as stopping the scroll when the cursor is hovering, for this we need to write such a thing in the main code block (inside $ (document) .ready (function () {})) structure :


 $('#viewport').hover(function(){ clearInterval(switchInterval); },function() { switchInterval = setInterval(nextSlide, slideInterval); }); 

To start analyzing this code, we need to know what switchInterval is . First, this is the variable that stores the periodic call to the nextSlide function, to put it simply, we have this line of code: setInterval (nextSlide, slideInterval); , turned into this: switchInterval = setInterval (nextSlide, slideInterval); . After these manipulations, our main code block took the following form:


 $(document).ready(function () { var switchInterval = setInterval(nextSlide, slideInterval); $('#viewport').hover(function(){ clearInterval(switchInterval); },function() { switchInterval = setInterval(nextSlide, slideInterval); }); }); 

Here I use the hover event, which means “when hovering”, this event allows me to track the moment when I hover over an object, in this case the viewport .


After hovering, I clear the interval, which I indicate in parentheses (this is our switchInterval ), then, separated by a comma, I write what I will do when I move the cursor back. In this block, I assign our nextInlt function a periodic call to the nextSlide function.


Now, if we check, we will see how our slider reacts to moving the cursor, stopping the slide switch.


So it's time to add buttons to our slider, let's start with the buttons back and forth.


First, mark them up:


 <div id="block-for-slider"> <div id="viewport"> <ul id="slidewrapper"> <li class="slide"><img src="img/1.jpg" alt="1" class="slide-img"></li> <li class="slide"><img src="img/2.jpg" alt="2" class="slide-img"></li> <li class="slide"><img src="img/3.jpg" alt="3" class="slide-img"></li> <li class="slide"><img src="img/4.jpg" alt="4" class="slide-img"></li> </ul> <div id="prev-next-btns"> <div id="prev-btn"></div> <div id="next-btn"></div> </div> </div> </div> 

At first, this markup may be incomprehensible, I will say right away that I wrapped these two buttons in one div with the prev-next-btns class just for your convenience, you can not do this, the result will not change, now we will add styles to them and everything will become clear:


 #prev-btn, #next-btn { position: absolute; width: 50px; height: 50px; background-color: #fff; border-radius: 50%; top: calc(50% - 25px); } #prev-btn:hover, #next-btn:hover { cursor: pointer; } #prev-btn { left: 20px; } #next-btn { right: 20px; } 

First, we position our buttons through position: absolute , thereby freely controlling their position inside our viewport , then we will specify the size of these buttons and round the corners with the help of border-radius so that these buttons turn into circles. Their color will be white, that is, #fff , and their indent from the top edge of the viewport will be equal to half the height of this viewport minus half the height of the button itself (in my case 25px), so we can arrange them vertically in the center. Next, we’ll point out that when we hover over them, our cursor will change to pointer and, eventually, we’ll let our buttons separately, that they should move 20px from their edges so that we can see them as we would like.


I repeat that you can style the page elements the way you want, I just give an example of the styles that I decided to use.


After styling, our slider should look something like this:
image
Next, go back to our js-file , where we describe the operation of our buttons. Well, add another function, it will show us the previous slide:


 function prevSlide() { if (slideNow == 1 || slideNow <= 0 || slideNow > slideCount) { translateWidth = -$('#viewport').width() * (slideCount - 1); $('#slidewrapper').css({ 'transform': 'translate(' + translateWidth + 'px, 0)', '-webkit-transform': 'translate(' + translateWidth + 'px, 0)', '-ms-transform': 'translate(' + translateWidth + 'px, 0)', }); slideNow = slideCount; } else { translateWidth = -$('#viewport').width() * (slideNow - 2); $('#slidewrapper').css({ 'transform': 'translate(' + translateWidth + 'px, 0)', '-webkit-transform': 'translate(' + translateWidth + 'px, 0)', '-ms-transform': 'translate(' + translateWidth + 'px, 0)', }); slideNow--; } } 

It is called prevSlide , it will only be called when you click on prev-btn . First, we check whether we are on the 1st slide or not, here we also check whether our slideNow has gone beyond the real range of our slides and, in the event that some of the conditions work, move to the last slide by shifting the slidewrapper to the value we need. We calculate this value using the formula: (width of one slide) * (number of slides is 1), we take all this with a minus sign, since we shift it to the left, it turns out that the viewport will now show us the last slide. At the end of this block, we also need to tell the variable slideNow that now in our field of view is the last slide.


If we are not on the first slide, then we need to move back 1, to do this, again we change the transform property of slidewrapper . The formula is as follows: (width of one slide) * (the number of the current slide is 2), all this, again, is taken with a minus sign. But why is -2, not -1, do we need to move just 1 slide back? The fact is that if we are, say, on the 2nd slide, then the variable x of the transform property : translate (x, 0) of our slidewrapper is already equal to the width of one slide, if we tell it that we need to take away the number of the current slide 1 then again we will get the unit to which the slidewrapper is already shifted, so you will need to shift by 0 these same viewport widths, which means to slideNow - 2.


Next, we simply subtract the unit from the variable slideNow , thereby indicating that we are already seeing the previous slide.


Now we need to add these lines to the main code block:


 $('#next-btn').click(function() { nextSlide(); }); $('#prev-btn').click(function() { prevSlide(); }); 

Here we just keep track of whether we clicked on our buttons, and in this case we call the functions we need, everything is simple and logical.


Now we’ll add navigation buttons on the slides, back to the markup again:


 <div id="block-for-slider"> <div id="viewport"> <ul id="slidewrapper"> <li class="slide"><img src="img/1.jpg" alt="1" class="slide-img"></li> <li class="slide"><img src="img/2.jpg" alt="2" class="slide-img"></li> <li class="slide"><img src="img/3.jpg" alt="3" class="slide-img"></li> <li class="slide"><img src="img/4.jpg" alt="4" class="slide-img"></li> </ul> <div id="prev-next-btns"> <div id="prev-btn"></div> <div id="next-btn"></div> </div> <ul id="nav-btns"> <li class="slide-nav-btn"></li> <li class="slide-nav-btn"></li> <li class="slide-nav-btn"></li> <li class="slide-nav-btn"></li> </ul> </div> </div> 

As you can see, a nested list appeared inside the viewport , give it the identifier nav-btns , inside it li - our navigation buttons, assign them the class slide-nav-btn , however you can finish the markup, proceed to the styles:


 #nav-btns { position: absolute; width: 100%; bottom: 20px; padding: 0; margin: 0; text-align: center; } .slide-nav-btn { position: relative; display: inline-block; list-style: none; width: 20px; height: 20px; background-color: #fff; border-radius: 50%; margin: 3px; } .slide-nav-btn:hover { cursor: pointer; } 

image
The nav-btns block , in which our buttons are located, is given the position: absolute property, so that it does not stretch the viewport in height, because in the slidewrapper property position: relative , we set 100% width to center the buttons with text-align: center horizontally relative to the viewport , then using the bottom property we make it clear to our block that it should be 20px from the bottom edge.


We do the same with the buttons as with the slides, but at the same time we now ask them to display: inline-block , since when display: inline, they do not respond to the width and height , since are in an absolutely positioned block. We will make their color white and with the help of the border-radius we already know will give them a circle shape. When you hover over them, we change the look of our cursor for the usual display.


And now we proceed to jQuery - parts :
First, let's declare the variable navBtnId, in which the index of the button we clicked will be stored:


 var navBtnId = 0; 

 $('.slide-nav-btn').click(function() { navBtnId = $(this).index(); if (navBtnId + 1 != slideNow) { translateWidth = -$('#viewport').width() * (navBtnId); $('#slidewrapper').css({ 'transform': 'translate(' + translateWidth + 'px, 0)', '-webkit-transform': 'translate(' + translateWidth + 'px, 0)', '-ms-transform': 'translate(' + translateWidth + 'px, 0)', }); slideNow = navBtnId + 1; } }); 

Here, when we click on our slide-nav-btn, we call the function, which first of all assigns the variable navBtnId to the index of the clicked button, that is, its sequence number, since the countdown starts from zero, then if we click on the second button, then navBtnId is written value 1. Next, we check where we add one to the button's ordinal number to get such a number, as if the count went not from 0, but from 1, compare this number with the number of the current slide, if they match, then we will not take any action, because the desired slide is already in viewport .


If the slide we need is not in the viewport's field of view, then we calculate the distance that we need to move the slidewrapper to the left, then change the value of the transform css-property to translate (the same distance in pixels, 0). This we have done more than once, so questions should not arise. At the end, we again save the value of the current slide to the variable slideNow , this value can be calculated by adding one to the index of the clicked button.


On this, in fact, everything, if something is not clear, then I leave a link to jsfiddle, where all the code written in the material will be provided.


→ Try on jsfiddle



Thanks for attention!


')

Source: https://habr.com/ru/post/319394/


All Articles