JavaScript - 图像滑块按钮不起作用

时间:2017-06-29 22:50:29

标签: javascript jquery

我正在学习JavaScript。现在我想创建一个典型的图像滑块,当页面加载时自动启动,如果单击2个按钮(向前和向后)中的一个,它将停止自动滑块,然后转到我们单击按钮的位置。

但是我正在测试的代码没有按钮工作。我甚至使用jQuery试图让它工作,但没有成功。我认为我弄得一团糟,但这就是代码:

$(function() {
  var slideIndex = 0;
  var i;
  var s = document.getElementsByClassName("slide");
  var stopslider = false;
  slider();
  
  $(".change[n]").click(function(){
    var slideIndex = 1;
    var stopslider = true;
    $( "slide1" ).removeClass( "slide" ).addClass( "1slide" );
    $( "slide2" ).removeClass( "slide" ).addClass( "1slide" );
    $( "slide3" ).removeClass( "slide" ).addClass( "1slide" );
    $( "slide4" ).removeClass( "slide" ).addClass( "1slide" );
    var s = document.getElementsByClassName("1slide");
    slideslide1Index += n;
    if (n > s.length) {
      slideIndex = 1
    } 
    if (n < 1) {
      slideIndex = s.length
    } ;
    for (i = 0; i < s.length; i++) {
      s[i].style.display = "none"; 
    }
    s[slideIndex-1].style.display = "block"; 
  });
  
  function slider() {
    for (i = 0; i < s.length; i++) {
      s[i].style.display = "none"; 
    }
    slideIndex++;
    if (slideIndex > s.length) {
      slideIndex = 1
    }
    s[slideIndex-1].style.display = "block";
    setTimeout(slider, 4000);
    if (stopslider= true) {
      clearTimeout(slider);
    } 
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<a href="imagem1"><img id="slide1" class="slide" src="imagens/imagemcentral1.jpg"></a>
<a href="imagem2"><img id="slide2" class="slide" src="imagens/imagemcentral2.jpg"></a>
<a href="imagem3"><img id="slide3" class="slide" src="imagens/imagemcentral3.jpg"></a>
<a href="imagem4"><img id="slide4" class="slide" src="imagens/imagemcentral4.jpg"></a>

<button id="previous" class="change" n="-1">previous</button>
<button id="latter" class="change" n="+1">latter</button>

2 个答案:

答案 0 :(得分:1)

(有关使用OP原始代码的答案,请参阅我的second answer。)

好的..所以我可能有点过分了:))

问题是,当我刚刚开始时,我做的与你一样,用一堆变量来存储进度和当前位置等。

但实际上,所有这些都是不必要的,并且JavaScript在这方面非常独特,因为页面上已经存在“物理”DOM结构,可以引用而不是使用专用变量。在许多情况下,它们可以作为“变量”,并且在许多情况下优先于(全局)变量。

无论如何,所以我几乎改变了你的整个代码,也重新命名了整个过程中的所有内容,删除了<a>标签之类的不必要的元素。您可能需要它们,但我想让代码尽可能干净,以便更容易理解:

阅读代码中的注释,了解发生了什么 忽略CSS,它仅用于样式。所有功能都在JS中。

PURE JS:

window.onload = function() {
  function changeSlide(d, id) {
  	var slides = document.getElementById(id).children[0];
    for (var i=0,count=slides.children.length; i<count; ++i) {
      if (slides.children[i].className.indexOf("active") != -1) {var slide=slides.children[i]; break;} //store the current slide
    }
    if (d=="next") {
      if (slides.lastElementChild.className.indexOf("active") != -1) {
        slides.firstElementChild.className += " active"; //loop around and activate the first slide
      } else {slide.nextElementSibling.className += " active";} //activate the next slide
    } else { //prev
      if (slides.firstElementChild.className.indexOf("active") != -1) {
        slides.lastElementChild.className += " active"; //loop around and activate the last slide
      } else {slide.previousElementSibling.className += " active";} //activate the prev slide
    }
    slide.className = slide.className.replace(" active",""); //deactivate the current slide
  }
  
//AUTOMATIC LOOP------------------------------
	function timer(id){setTimeout(function(){if (document.getElementById(id).className.indexOf("auto") != -1) {changeSlide("next",id); timer(id);}},4000);}
  for (var i=0,s=document.getElementsByClassName("slider"),count=s.length; i<count; ++i) {timer(s[i].id);} //create a timer-loop for every slider
  
//EVENT-HANDLERS------------------------------
  for (var i=0,s=document.getElementsByClassName("slider"),count=s.length; i<count; ++i) {
    s[i].onmousedown = function(){return false;}; //otherwise sometimes the space next to the slider gets selected on navigation
    //click-handlers for prev/next buttons
    for (var j=0,c=s[i].children.length; j<c; ++j) {
      if (s[i].children[j].className.indexOf("nav") != -1) {
        s[i].children[j].onclick = function() {
        	var s = document.getElementById(this.parentNode.id);
          if (s.className.indexOf("auto") != -1) {s.className = s.className.replace(" auto","");} //stop the automatic loop
          changeSlide(this.className.split(" ")[1],this.parentNode.id); //prev/next slide ('this.className.split(" ")[1]' returns the second classname)
        };
      }
    }
  }
};
.slider {display:inline-block; position:relative; width:240px; height:135px; background:#000;}
.slider .slides {width:100%; height:100%;}
.slider .slides .slide {float:left; width:0; height:100%; background:center center/contain no-repeat; transition:width 0.5s ease 0s;}
.slider .slides .slide.active {width:100%;}

.slider .nav {position:absolute; top:0; width:15%; min-width:44px; height:100%; background:#888; opacity:0; cursor:pointer;}
.slider:hover .nav {opacity:0.3;}
.slider .nav.prev {left:0;}
.slider .nav.next {right:0;}
.slider .nav .btn {position:absolute; top:0; bottom:0; width:34px; height:34px; margin:auto 0; box-sizing:border-box; border:2px solid #ddd; border-radius:999px; background:#555; opacity:0.7; visibility:hidden;}
.slider .nav.prev .btn {left:5px;}
.slider .nav.next .btn {right:5px;}
.slider:hover .nav .btn {visibility:visible;}
.slider:hover .nav .btn:hover {border-color:#fff; opacity:1;}

.slider .nav .btn .arrow {position:absolute; top:0; bottom:0; width:0; height:0; margin:auto 0; border:10px solid transparent;}
.slider .nav.prev .btn .arrow {right:calc(50% - 3px); border-right-color:#ddd;}
.slider .nav.next .btn .arrow {left:calc(50% - 3px); border-left-color:#ddd;}
.slider .nav.prev .btn:hover .arrow {border-right-color:#fff;}
.slider .nav.next .btn:hover .arrow {border-left-color:#fff;}
<div class="slider auto" id="slider1">
  <div class="slides">
    <div class="slide active" style="background-image:url('https://placeimg.com/320/180/arch');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/250/animals');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/720/450/tech/sepia');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/480/480/nature');"></div>
  </div>
  <div class="nav prev"><div class="btn"><div class="arrow"></div></div></div>
  <div class="nav next"><div class="btn"><div class="arrow"></div></div></div>
</div>

<div class="slider auto" id="slider2">
  <div class="slides">
    <div class="slide active" style="background-image:url('https://placeimg.com/320/480/nature');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/480/people/sepia');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/180/tech');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/360/arch/sepia');"></div>
  </div>
  <div class="nav prev"><div class="btn"><div class="arrow"></div></div></div>
  <div class="nav next"><div class="btn"><div class="arrow"></div></div></div>
</div>
jsfiddle:https://jsfiddle.net/9pommada/9/

  • 我这样做是为了您可以在页面中添加多个滑块,它们将彼此独立工作。我通过移除(几乎)所有id并仅使用类来完成此操作 剩下的唯一id就在.slider上,如果没有它们,我就无法在纯JS中使用它。
    如果您根本不需要id,请查看下面的jQuery版本。
  • for循环可能看起来有点奇怪。基本上,我没有做更熟悉的版本for (var i=0; i<slides.children.length; i++) {,而是在for循环的第一部分声明了一个额外的变量,因此不会在每次迭代时计算length。结果是以下for (var i=0,count=slides.children.length; i<count; ++i) {。使用++i的{​​{3}}超过i++,但是这样使用没有实际区别。
  • 我说所有的功能都在JS中,这并不完全正确。 CSS中有一些东西对滑块的行为方式有很大的影响。虽然它主要是花哨的过渡,但不久之前你也不得不在JavaScript中编写代码,所以它绝对是我认为的功能的一部分。
    一个是transition:width 0.5s ease 0s;。与float:left;一起使幻灯片真正滑动,而不仅仅是静态替换 另一个是background:center center/contain no-repeat;。这使得图像总是很好地居中并缩放以适合容器。如果图像太宽则会垂直居中,如果图像太高则会水平居中。这就是所有的CSS。
  • 您最初可能忽略的另一个重要问题是,要使上述点(关于图像居中和缩放)起作用,您需要将<img/>标签替换为<div> s,然后再打开那些<div>将图片设置为background-images 我在这里用HTML做过,这通常被认为是不好的做法,但是如果你将它们移到CSS上,那么你必须为每张幻灯片提供一个唯一的classid。< / LI>

JQUERY:

$(function() {
  function changeSlide(d, slides) {
    var slide = $(slides).children(".slide.active")[0]; //store the current slide
    if (d=="next") {
      if ($(slides).children(".slide").last().hasClass("active")) {
        $(slides).children(".slide").first().addClass("active"); //loop around and activate the first slide
      } else {$(slide).next().addClass("active");} //activate the next slide
    } else { //prev
      if ($(slides).children(".slide").first().hasClass("active")) {
        $(slides).children(".slide").last().addClass("active"); //loop around and activate the last slide
      } else {$(slide).prev().addClass("active");} //activate the prev slide
    }
    $(slide).removeClass("active"); //deactivate the current slide
  }
  
//AUTOMATIC LOOP------------------------------
	function timer(slides){setTimeout(function(){if ($(slides).parent().hasClass("auto")) {changeSlide("next",slides); timer(slides);}},4000);}
  $(".slider").each(function(){timer($(this).children(".slides")[0]);}); //create a timer-loop for every slider
  
//EVENT-HANDLERS------------------------------
  $(".slider").on("mousedown",function(){return false;}); //otherwise sometimes the space next to the slider gets selected on navigation
  $(".slider .nav").click(function(){
    if ($(this).closest(".slider").hasClass("auto")) {$(this).closest(".slider").removeClass("auto");}; //stop the automatic loop
    changeSlide(this.className.split(" ")[1],$(this).siblings(".slides")[0]); //prev/next slide
  });
});
.slider {display:inline-block; position:relative; width:240px; height:135px; background:#000;}
.slider .slides {width:100%; height:100%;}
.slider .slides .slide {float:left; width:0; height:100%; background:center center/contain no-repeat; transition:width 0.5s ease 0s;}
.slider .slides .slide.active {width:100%;}

.slider .nav {position:absolute; top:0; width:15%; min-width:44px; height:100%; background:#ddd; opacity:0; cursor:pointer;}
.slider:hover .nav {opacity:0.3;}
.slider .nav.prev {left:0;}
.slider .nav.next {right:0;}
.slider .nav .btn {position:absolute; top:0; bottom:0; width:34px; height:34px; margin:auto 0; box-sizing:border-box; border:2px solid #ddd; border-radius:999px; background:#555; opacity:0.7; visibility:hidden;}
.slider .nav.prev .btn {left:5px;}
.slider .nav.next .btn {right:5px;}
.slider:hover .nav .btn {visibility:visible;}
.slider:hover .nav:hover .btn {opacity:1;}

.slider .nav .btn .arrow {position:absolute; top:0; bottom:0; width:0; height:0; margin:auto 0; border:10px solid transparent;}
.slider .nav.prev .btn .arrow {right:calc(50% - 3px); border-right-color:#ddd;}
.slider .nav.next .btn .arrow {left:calc(50% - 3px); border-left-color:#ddd;}
.slider .nav.prev:hover .btn .arrow {border-right-color:#fff;}
.slider .nav.next:hover .btn .arrow {border-left-color:#fff;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="slider auto">
  <div class="slides">
    <div class="slide active" style="background-image:url('https://placeimg.com/320/180/arch');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/250/animals');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/720/450/tech/sepia');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/480/480/nature');"></div>
  </div>
  <div class="nav prev"><div class="btn"><div class="arrow"></div></div></div>
  <div class="nav next"><div class="btn"><div class="arrow"></div></div></div>
</div>

<div class="slider auto">
  <div class="slides">
    <div class="slide active" style="background-image:url('https://placeimg.com/320/480/nature');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/480/people/sepia');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/180/tech');"></div>
    <div class="slide" style="background-image:url('https://placeimg.com/640/360/arch/sepia');"></div>
  </div>
  <div class="nav prev"><div class="btn"><div class="arrow"></div></div></div>
  <div class="nav next"><div class="btn"><div class="arrow"></div></div></div>
</div>
jsfiddle:subtle difference

  • 因为我们可以使用jQuery对象,所以我们可以删除所有id,这样可以更灵活地在其他网站上实现。

您选择哪一个可能主要取决于偏好。我个人更喜欢jQuery,因为它让生活变得如此简单,而且我已经将它用于其他任何事情了。但是当我刚开始的时候,我真的很怀疑它,而纯JS中的编码确实帮助我很好地理解了我在做什么。无论如何,希望我能提供帮助,如果您对代码有任何疑问,请将其留在评论中,我会尽力回答。

答案 1 :(得分:1)

我又看了一眼first answer并意识到这可能完全不是你要找的东西。
所以在这里我尽量保持原始代码的真实性。

请参阅代码段下方的评论以获取解释。

&#13;
&#13;
window.onload = function() {
  var slideIndex = 0;
  var stopslider = false;
  slider();
  
  function change(n) {
    stopslider = true;
    var s = document.getElementsByClassName("slide");
    slideIndex += n;
    if (slideIndex > s.length) {
      slideIndex = 1;
    } else if (slideIndex < 1) {
      slideIndex = s.length;
    }
    for (var i=0; i<s.length; i++) {
      s[i].style.display = "none";
    }
    s[slideIndex-1].style.display = "block";
  }
  
  function slider() {
    if (stopslider == false) {
      var s = document.getElementsByClassName("slide");
      for (var i=0; i<s.length; i++) {
        s[i].style.display = "none";
      }
      slideIndex++;
      if (slideIndex > s.length) {
        slideIndex = 1;
      }
      s[slideIndex-1].style.display = "block";
      setTimeout(slider, 4000);
    }
  }
  
//CLICK-HANDLERS-------------------------
  document.getElementById("previous").onclick = function(){change(-1);};
  document.getElementById("latter").onclick = function(){change(+1);};
};
&#13;
<a class="slide" href="imagem1"><img src="https://placeimg.com/200/150/animals"></a>
<a class="slide" href="imagem2"><img src="https://placeimg.com/200/150/arch"></a>
<a class="slide" href="imagem3"><img src="https://placeimg.com/200/150/people"></a>
<a class="slide" href="imagem4"><img src="https://placeimg.com/200/150/tech"></a>

<button id="previous" class="change">previous</button>
<button id="latter" class="change">latter</button>
&#13;
&#13;
&#13; jsfiddle:https://jsfiddle.net/Lkeaejkn/

  • 既然你说原来是用纯JS编写的,我就把所有的jQuery都还原了 因此$(function() {变为window.onload = function() {
  • 我删除了全局变量var s = document.getElementsByClassName("slide");。您可以使用它,但由于您已经在一个函数中声明它,并且您通常希望将全局变量保持在最小值(link1link2),我选择删除全局变量。
    我也删除了var i;,原因相同。最好在for-loop中声明它们。
  • <button class="change" n="+1">".change[n]"不是我熟悉的,无论是HTML,纯JS还是jQuery。我不认为它可能(如果我错了,有人会纠正我)
    您无法构建自己的HTML属性。好吧,你有点可以,使用data-* attribute。您可以使用它们,如果您愿意,请查看下面的第二个代码段 在这个片段中,我选择了在JS中使用onclick-handlers的另一种方式 (将所有HTML和JS分开是一种更好的做法,所以尽管如此,这个选项可能会更好。但是对于这个选项,你需要给出按钮id s - 你已经有了。使用数据属性,那些id不是必需的。)
    在您的JS中,将$(".change[n]").click(function(){更改为常规函数:function change(n) {,其中n包含+1-1的值,用于确定滑块的方向。
    在代码的底部,我添加了两个点击处理程序,它们都调用函数change(n),并沿参数n发送,值为-1+1。< / LI>
  • 在内部函数change(n)中,我删除了var slideIndex = 1;,因为这会覆盖/干扰您在脚本开头已声明的全局变量var slideIndex不幸的是,这个变量必须保持全局,否则每次调用函数change(n)时都会重置该值,幻灯片永远不会改变。这是我创建第一个答案的原因之一,以避免全局变量。如果您有兴趣,请查看that one
    1. 我从var删除了var stopslider = true;var创建一个只在函数内可见的新变量(所以不是全局的),但在这种情况下我们需要引用全局var stopslider,因为这是在内部检查的变量函数slider()确定是否应该停止自动滑块。
    2. 我删除了所有$( "slide1" ).removeClass( "slide" ).addClass( "1slide" );。我不知道你在那里尝试了什么,但没有必要。 (另外,id的jQuery选择器需要#前面的id,所以:$("#slide1"))。
      我还继续从HTML中的幻灯片中删除了所有id,因为它们不是必需的,如果您想稍后插入更多幻灯片,它可以为您节省很多痛苦。
    3. 我还从1删除了var s = document.getElementsByClassName("1slide");,也不知道你在那里做了什么。
      我还将class="slide"<img/>移到了<a>,因为否则图片会被隐藏,但所有图片的<a>仍然是可见,这不是你想要的 您实际上不需要图片的<a>或滑块本身,但您可能有特定目的,所以我会留下它们。
    4. 我将slideslide1Index += n;更改为slideIndex += n;,因此它引用了全局变量。
  • 在您的所有if子句中,您检查了nif (n > s.length) {,但是您应该检查slideIndex。请注意,n的值只有-1+1。全局slideIndex包含当前幻灯片的值。
  • 我将你的两个if-clauses组合成一个if-else:} else if (slideIndex < 1) {。因为只有两个子句中的一个可以为真,所以每次调用change(n)时都无法运行它们。这也直接显示(对于读取代码的程序员)这两个条款属于一起,是一个更大的检查的一部分。
  • 你有一个拼写错误:} ;,我删除了它。
  • 正如我之前所说,最好在for循环中声明i,因此变为:for (var i=0; i<s.length; i++) {(在函数slider()中相同)。
  • 内部函数slider(),因为我删除了全局var s = document.getElementsByClassName("slide");,我必须在此函数的顶部添加该行,就像在change(n)中一样。
  • 在if子句条件下,我将if (stopslider= true) {更改为if (stopslider == true) { 由于=已用于分配值,因此在编程中我们使用==(double =)来检查两个值是否相等。
  • 为了能够清除超时,您可能首先需要在设置时存储对该计时器的全局引用,因此:timer = setTimeout(slider,4000);,其中timer是全局{{1}你在脚本开头设置的 幸运的是,我们实际上并不需要清除计时器。因为var只运行一次而在此之后才停止,我们只需要不再设置它 为了做到这一点,只需将函数setTimeout()中的所有代码放在slider()周围使用的if子句中,只将clearTimeout()更改为true:{{1 }}。
    (如果仅将其放在false左右,则在您第一次点击按钮后,滑块仍会自动更改一次。)

我更改了图片的if (stopslider == false) {,这样我们才能真正看到它们发生变化。

使用setTimeout()属性的代码段:

此代码段基于之前的代码段,只有一些更改。

&#13;
&#13;
src
&#13;
data-
&#13;
&#13;
&#13; jsfiddle:https://jsfiddle.net/Lkeaejkn/2/

  • 在HTML中,我将window.onload = function() { var slideIndex = 0; var stopslider = false; slider(); function slider() { if (stopslider == false) { var s = document.getElementsByClassName("slide"); for (var i=0; i<s.length; i++) { s[i].style.display = "none"; } slideIndex++; if (slideIndex > s.length) { slideIndex = 1; } s[slideIndex-1].style.display = "block"; setTimeout(slider, 4000); } } //CLICK-HANDLERS------------------------- (function() { var c = document.getElementsByClassName("change"); for (var i=0; i<c.length; i++) { c[i].onclick = function() { stopslider = true; var n = parseInt(this.getAttribute("data-n")); var s = document.getElementsByClassName("slide"); slideIndex += n; if (slideIndex > s.length) { slideIndex = 1; } else if (slideIndex < 1) { slideIndex = s.length; } for (var i=0; i<s.length; i++) { s[i].style.display = "none"; } s[slideIndex-1].style.display = "block"; }; } })(); };<a class="slide" href="imagem1"><img src="https://placeimg.com/200/150/animals"></a> <a class="slide" href="imagem2"><img src="https://placeimg.com/200/150/arch"></a> <a class="slide" href="imagem3"><img src="https://placeimg.com/200/150/people"></a> <a class="slide" href="imagem4"><img src="https://placeimg.com/200/150/tech"></a> <button class="change" data-n="-1">previous</button> <button class="change" data-n="+1">latter</button>添加到相应的按钮,并从按钮中删除data-n="-1",因为它们不再需要。 Read about the data-* attribute
  • 在JS中,我删除了旧的基于id的点击处理程序,而是将整个函数data-n="+1"更改为按钮的匿名点击处理程序。
  • 我在self-executing anonymous function中包含了点击处理程序,以防止出现更多全局变量:id
  • 然后我使用与幻灯片相同的原理,但现在迭代按钮 然后对于每个按钮,我绑定实际的点击处理程序:change(n)
  • 点击处理程序内部使用(function() { ... })();从相应按钮获取c[i].onclick = function() { - 值。
    由于var n = parseInt(this.getAttribute("data-n"));属性中的数据采用文本格式,因此需要n才能将文本值转换为整数。