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