Controle deslizante de imagem com botão anterior / próximo e pager em JavaScript

Em mim último blog <a href= “https://coderwall.com/p/vsdrug?i=1&p=1&q=&t%5B%5D=%21%21mine&t%5B%5D=%21%21bookmarks”> ” Como para criar um controle deslizante de imagem com javascirpt “</a>, programei um controle deslizante de imagem básico.
Em seguida, crio um controle deslizante de imagem com o botão anterior / próximo.

Demo: http://cssdeck.com/labs/imageslider-button

Controle deslizante de imagem com botão anterior / próximo e pager:

Demo: http://cssdeck.com/labs/imageslider-pager

Na verdade, esses dois programas usam a mesma função principal. Acho que este é um bom exemplo de reutilização de código 🙂

Sou um desenvolvedor web iniciante. com a ajuda do meu amigo, entendi melhor como projetar a arquitetura do código. Mas ainda há muito a aprender.

Parte HTML: praticamente igual ao controle deslizante básico do último blog:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="Image-Slider-LnR.js"></script>
<link rel="stylesheet" type="text/css" href="Image-Slider-LnR.css">
</head>
<body>
<div class="container">
<div class="slider_wrapper">
<ul id="image_slider">
<li><img src="./image/1.jpg"></li>
<li><img src="./image/4.jpg"></li>
<li><img src="./image/5.jpg"></li>
<li><img src="./image/4.jpg"></li>
<li><img src="./image/1.jpg"></li>
<li><img src="./image/5.jpg"></li>
</ul>
<span class="nvgt" id="prev"></span>
<span class="nvgt" id="next"></span>
</div>
</div>
</body>
</html>

Parte CSS: apenas a parte do botão anterior / seguinte. As outras partes são iguais ao controle deslizante básico

.nvgt{
position
:absolute;
top
: 120px;
height
: 50px;
width
: 30px;
opacity
: 0.6;
}
.nvgt:hover{
opacity
: 0.9;
}
#prev{
background
: #000 url('./image/prev.png') no-repeat center;
left
: 0px;
}
#next{
background
: #000 url('./image/next.png') no-repeat center;
right
: 0px;
}

A parte JavsScript é um pouco diferente.

Parte 1 init ()

function init(){
ul
= document.getElementById('image_slider');
liItems
= ul.children;
imageNumber
= liItems.length;
imageWidth
= liItems[0].children[0].clientWidth;
// set ul's width as the total width of all images in image slider.
ul
.style.width = parseInt(imageWidth * imageNumber) + 'px';
prev
= document.getElementById("prev");
next = document.getElementById("next");
/*.onclike = onClickPrev() will be fired when onload; is this because closure?? */
prev
.onclick = function(){ onClickPrev();};
next.onclick = function(){ onClickNext();};
}

Nota:

É semelhante ao controle deslizante básico. Ao clicar no botão anterior e próximo, uma função diferente será chamada.

O motivo pelo qual foi projetado dessa forma é que será mais fácil definir limites e reagir de maneira diferente.

Se a imagem atual for a primeira imagem, clique no botão anterior, o controle deslizante irá até a última imagem;

Se a imagem atual for a última, clique no botão próximo, o controle deslizante irá até a primeira imagem;

Ainda não descobri por que não consigo atribuir onClickPrev () a prev.onclick diretamente assim:

prev.onclick = onClickPrev();

Sempre que faço isso, onClickPrev () será disparado quando init () está sendo chamado. Acho que é por causa do encerramento, mas não tenho certeza. Vou dar uma olhada.

Parte 2 onClickPrev (), onClickNext () e slideTo ()

/**
* clicking prev. if current image is the first image, ul slide all the way to the last one

* otherwise, it slide to the image on the left of current image.

**/

function onClickPrev(){
if (currentImage == 0){
slideTo
(imageNumber - 1);
}
else{
slideTo
(currentImage - 1);
}
}

/**
* clicking next. if current image is the last image, ul slide all the way to the first one

* otherwise, it slide to the image on the right of current image.

**/


function onClickNext(){
if (currentImage == imageNumber - 1){
slideTo
(0);
}
else{
slideTo
(currentImage + 1);
}
}
/**
* slideTo is the function that actually does the movement.

* it takes one variable--imageToGo as parameter. it's an int stands for the image will be displayed

* By comparing imageToGo and currentImage, it can be decided which direction to move, left or right

* left: direction = -1; right: direction = 1

* so the new left position is the current postion plus/minus (number of imagesToGo * image width)

* when the step function is finished, a callback function will be called to set current image to imageToGo

**/

function slideTo(imageToGo){
var direction;
var numOfImageToGo = Math.abs(imageToGo - currentImage);
direction
= currentImage > imageToGo ? 1 : -1;
currentPosition
= -1 * currentImage * imageWidth;
var opts = {
duration
:1000,
delta
:function(p){return p;},
step
:function(delta){
ul
.style.left = parseInt(currentPosition + direction * delta * imageWidth * numOfImageToGo) + 'px';
},
callback
:function(){currentImage = imageToGo;}
};
animate
(opts);
}

Nota:

Existe uma variável pública currentImage, e slideTo aceita outra variável, imageToGo.
com a função slideTo (), comparo essas duas variáveis ​​para decidir para a esquerda ou direita para a qual deslizar e o número de imagens a serem transmitidas.

Depois de obter essas duas variáveis-chave, posso deslizar a imagem para a posição atual e mover os pixels certos na direção correta.

Função de animação genérica da Parte 3: assim como o controle deslizante básico:

function animate(opts){
var start = new Date;
var id = setInterval(function(){
var timePassed = new Date - start;
var progress = timePassed / opts.duration;
if (progress > 1){
progress
= 1;
}
var delta = opts.delta(progress);
opts
.step(delta);
if (progress == 1){
clearInterval
(id);
opts
.callback();
}
}, opts.delay || 17);
}
window
.onload = init;

Sim ~~~ 🙂 Agora temos um controle deslizante de imagem com o botão anterior / próximo.

Se quisermos ter um pager, basta usar slideTo () !

Eu realmente gosto dessa sensação: flexível e fácil de manter 🙂

HTML e CSS: wrapper externo, ad a ul. Porque eu quero que seja flexível, então não há código dentro da tag ul.

<ul id="pager"></ul>

#pager{

/* firefox has different center method. this doesn't work for fire fox */

/* not in the center*/

padding:0px;

position:relative;

height:50px;

margin:auto;

margin-top:10px;

}

#pager li{

padding: 0px;

margin:5px;

width:20px;

height:20px;

border:1px solid white;

color:white;

list-style: none;

opacity: 0.6;

float:left;

border-radius: 3px;

cursor: pointer;

}

#pager li:hover{

opacity:0.9;

}

JavaScript adiciona mais uma função, generatePager ()

function generatePager(imageNumber){    
var pageNumber;
var pagerDiv = document.getElementById('pager');
for (i = 0; i < imageNumber; i++){
var li = document.createElement('li');
pageNumber
= document.createTextNode(parseInt(i + 1));
li
.appendChild(pageNumber);
pagerDiv
.appendChild(li);
// add event inside a loop, closure issue.
li
.onclick = function(i){
return function(){
slideTo
(i);
}
}(i);
}
// style.width can't get width from css sheet.
var computedStyle = document.defaultView.getComputedStyle(li, null);
//border width 1px; offsetWidth = 22; offsetWidth returns a number
var liWidth = li.offsetWidth;
// remove px from the string returned. like '5px'-->'5'
var liMargin = parseInt(computedStyle.margin.replace('px',""));
// margin on both left and right side.
pagerDiv
.style.width = parseInt((liWidth + liMargin * 2) * imageNumber) + 'px';
}

Aqui está uma coisa que eu quero mencionar: adicione evento a li dentro de um loop

Mas desta vez, li.onclick = function () {slideTo (i); } não funciona.

Acho que também é um problema de fechamento. Vou ler sobre o fechamento e postar um blog sobre isso mais tarde.

Exceto pelo problema de encerramento, sempre fico confuso sobre como organizar meu código ou a arquitetura do código. Eu preciso ler alguns livros sobre padrões de design? Talvez.

周 周 加油!

Guangyi Zhou