代码之家  ›  专栏  ›  技术社区  ›  Laiqa Mohid

vanilla javascript和css图像滑块工作不正常

  •  0
  • Laiqa Mohid  · 技术社区  · 4 年前

    我用一些javascript和css创建了一个包含许多图像的图像滑块。我只是使用client width来获得图像的大小(变化很小),并用一个计数器变量计算translateX距离。最后添加了css转换。然而,我似乎无法得到滑块来正确地翻译整个图像。我不知道为什么会出错。我在计算响应性时使用了“vw”。我对javascript是新手,我也很喜欢其他部分代码的任何提示。

    这里是JS fiddle链接- https://jsfiddle.net/n6smpv2j/15/

    HTML格式

    <div id="lookbook" data-tab-content class="black-text">
                <div class="lookbook-nav">
                   <button id="left">←</button>
                   <button id="right">→</button>
                </div>
                <div class="lookbook">
                   <div class="slider">
                      <img src="https://loremflickr.com/640/360" id="lastClone" alt="">
                      <img src="https://picsum.photos/640/400">
                      <img src="https://loremflickr.com/640/360">
                      <img src="https://picsum.photos/640/400">
                      <img src="https://loremflickr.com/640/360">
                      <img src="https://picsum.photos/640/400">
                      <img src="https://loremflickr.com/640/360">
                      <img src="https://picsum.photos/600/400">
                      <img src="https://fillmurray.com/600/330">
                      <img src="https://picsum.photos/600/400">
                      <img src="https://fillmurray.com/600/330">
                      <img src="https://picsum.photos/600/400">
                      <img src="https://loremflickr.com/640/360">
                      <img src="https://picsum.photos/600/400">
                      <img src="https://loremflickr.com/640/360">
                      <img src="https://picsum.photos/600/400" id="firstClone" alt="">
                   </div>
                </div>
             </div>
    

    JS公司

    const slider = document.querySelector('.slider');
    const sliderImages = document.querySelectorAll('.slider img');
    const leftbtn = document.querySelector('#left');
    const rightbtn = document.querySelector('#right');
    let counter = 1;
    const size = sliderImages[0].clientWidth;
    slider.style.transform = 'translateX(' + (-size * counter) + 'vw)';
    
    rightbtn.addEventListener('click', () => {
       if (counter >= sliderImages.length - 1) return;
       slider.style.transition = "transform 0.4s ease-in";
       counter++;
       slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
    })
    
    leftbtn.addEventListener('click', () => {
       if (counter <= 0) return;
       slider.style.transition = "transform 0.4s ease-in";
       counter--;
       slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
    })
    
    slider.addEventListener('transitionend', () => {
       if (sliderImages[counter].id === "lastClone") {
          slider.style.transition = "none";
          counter = sliderImages.length - 2;
          slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
       }
       if (sliderImages[counter].id === "firstClone") {
          slider.style.transition = "none";
          counter = sliderImages.length - counter;
          slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
       }
    })
    

    CSS格式

    #lookbook {
       width: 100vw;
       height: 100vh;
    }
    
    .lookbook-nav {
       width: 70vw;
       height: 10vh;
       margin-left: 15vw;
       margin-top: 45vh;
       position: absolute;
       display: flex;
       justify-content: space-between;
       align-items: center;
    }
    
    button {
       border: none;
       outline: none;
       background: transparent;
       font-size: 2rem;
       /* font-weight: bold; */
       cursor: pointer;
    }
    
    .lookbook-nav button {
       border: none;
       outline: none;
       background: transparent;
       font-size: 2rem;
       /* font-weight: bold; */
       cursor: pointer;
    }
    
    button:hover {
       opacity: 0.4;
    }
    
    .lookbook {
       width: 56vw;
       height: 91vh;
       margin: auto;
       overflow: hidden;
    }
    
    .lookbook img {
       width: 100%;
       height: auto !important;
    }
    
    .slider {
       margin-top: 10vh;
       display: flex;
       width: auto;
       
    }
    
    0 回复  |  直到 4 年前
        1
  •  2
  •   A Haworth    4 年前

    来自@DecjazMach的答案解决了最重要的问题,但并没有涵盖所有问题。例如,解决方案仍然使用第一个图像的宽度来设置可见滑块的宽度。这在很多情况下都是好的,但是如果第一张照片是一张瘦高的肖像,而其他的是风景画,或者反之亦然呢?

    @Laiqa-Mohid也欢迎任何其他的建议,因此这里有一些来自于简化事情的建议,例如最小化JS中需要的计算和系统在点击时必须完成的“工作”。 http://bayeuxtapestry.rgspaces.org.uk/slider

    笔记:

    滑块可见部分的大小不依赖于第一个图像的尺寸

    img已经被divs+背景图像所取代,这样就可以适应不同的大小/宽高比,而不需要任何javascript计算—这将自动帮助响应

    这些div都具有相同的尺寸,因此滑块需要移动的量不取决于图像的大小

    使用变换:translateX works但需要在Javascript中进行计算。我们可以使用CSS动画代替,只需要移动当前可见的幻灯片和下一个要显示的幻灯片。

    图像服务有时不提供图像,所以我使用了我自己的-故意不同的大小和纵横比(包括肖像)

    使用这种方法,可以有一个连续的滑块-显示第一张幻灯片,如果用户点击过去的最后一个。

    <!DOCTYPE html>
    <html>
    <head>
    <title>Slider</title>
    <meta charset="utf-8">
    <style>
    #lookbook {
      width: 100vw;
      height: 100vh;
      margin:0;
      padding:0;
      overflow:hidden;
    }
    
    .lookbook-nav {
      width: 70vw;
      height: 10vh;
      margin-left: 15vw;
      margin-top: 45vh;
      position: absolute;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    
    button {
      border: none;
      outline: none;
      background: transparent;
      font-size: 2rem;
      /* font-weight: bold; */
      cursor: pointer;
    }
    
    .lookbook-nav button {
      border: none;
      outline: none;
      background: transparent;
      font-size: 2rem;
      /* font-weight: bold; */
      cursor: pointer;
    }
    
    button:hover {
      opacity: 0.4;
    }
    
    div .lookbook {
      width: 56vw;
    }
    
    .lookbook {
      height: 91vh;
      margin: auto;
      overflow: hidden;
    }
    
    div.slider{
      margin:0;
      margin-top: 10vh;
      height:81vh;/* this is height of (lookbook - margin-top) - probably better done through flex */
      position:relative;
      top:0;
      padding:0;
      width:100%;
    }
    
    @keyframes slideouttoleft {
      from {
       left: 0;
       visibility:visible;
      }
      to {
       left: -100%;
       visibility:hidden;
      }
    }
    @keyframes slideinfromright {
      from {
       left: 100%;
       visibility:visible;
      }
      to {
       left: 0;
       visibility:visible;
      }
    }
    @keyframes slideouttoright {
      from {
       left: 0;
       visibility:visible;
      }
      to {
       left: 100%;
       visibility:hidden;
      }
    }
    @keyframes slideinfromleft {
      from {
       left: -100%;
       visibility:visible;
      }
      to {
       left: 0;
       visibility:visible;
      }
    }
    
    .slider div {
      position:absolute;
      top:0;
      left:0;
      overflow:hidden;
      visibility:hidden;
      margin: 0;
      padding: 0;
      width:100%;
      height:100%;
      background-size: contain;
      background-position: center center;
      background-repeat: no-repeat no-repeat;
      animation-duration: 0.4s;
      animation-delay: 0s;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-timing-function: ease-in;
      animation-fill-mode: forwards;
    }
    </style>
    </head>
    <body>
    
    <div id="lookbook" data-tab-content class="black-text">
            <div class="lookbook-nav">
              <button id="left">←</button>
              <button id="right">→</button>
            </div>
            <div class="lookbook">
              <div class="slider">
              <!-- images taken from Reading (UK) Museum's Victorian copy of the Bayeux Tapestry -->
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/boat-and-horses-768x546.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/two-horses-300x212.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/woman-and-child-1200x901.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/archer-2-768x1100.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/boat-builder-2-878x1024.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/group-1-768x603.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/pointing-horseman-768x853.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/group-2-768x619.png);"></div>
                <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/carrying-casket-768x556.png);"></div>
              </div>
            </div>
    </div>
    <script>
    const slider = document.querySelector('.slider');
    const sliderImages = document.querySelectorAll('.slider div');
    const leftbtn = document.querySelector('#left');
    const rightbtn = document.querySelector('#right');
    const numImgs=sliderImages.length;
    let curImg = 0;
    
    rightbtn.addEventListener('click', () => {
      sliderImages[curImg].style.animationName='slideouttoleft';
      curImg=(curImg+1)%numImgs;
      sliderImages[curImg].style.animationName='slideinfromright';
    })
    
    leftbtn.addEventListener('click', () => {
      sliderImages[curImg].style.animationName='slideouttoright';
      curImg=curImg==0? numImgs-1 : Math.abs((curImg-1)%numImgs);
      sliderImages[curImg].style.animationName='slideinfromleft';
    })
    
    function initialize() {
      sliderImages[0].style.animationName='slideinfromright';
    }
    
    window.onload=initialize;
    
    </script>
    </body>
    </html>
    
        2
  •  2
  •   Dharman chazomaticus    4 年前

    size 正在以像素为单位进行计算,如您所见 here . 所以要得到宽度 vw 您可以使用以下函数作为

    const size = vw(sliderImages[0].clientWidth);
    
    function vw(v) {
        var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
        return (v * w) / 100;
    }
    
        3
  •  0
  •   Souhailhimself    4 年前

    出于某种原因,从该源加载的图像不起作用,所以我在本地下载了它们,它们确实起作用了,我也对你的CSS做了一些修改。

    var slider = document.getElementById("slider");
    var slides = slider.childElementCount;
    var i = 0;
    document.getElementById("right").addEventListener("click", function () {
      i == slides - 1 ? (i = 0) : i++;
      slider.style.transform = "translate(-" + 600 * i + "px)";
    });
          body {
            background-color: aqua;
          }
          #lookbook {
            position: relative;
            box-sizing: content-box;
            height: auto;
            max-width: 600px;
            margin: auto;
          }
    
          .lookbook-nav {
            position: absolute;
            display: flex;
            justify-content: space-between;
            width: 100%;
            height: 100%;
          }
    
          button {
            border: none;
            outline: none;
            background: transparent;
            font-size: 2rem;
            cursor: pointer;
          }
    
          .lookbook-nav button {
            border: none;
            outline: none;
            background: transparent;
            font-size: 2rem;
            /* font-weight: bold; */
            cursor: pointer;
            color: beige;
            z-index: 2;
          }
    
          button:hover {
            opacity: 0.4;
          }
    
          .lookbook {
            width: auto;
            height: 91vh;
            margin: auto;
            overflow: hidden;
          }
    
          .lookbook img {
            width: 600px;
            height: auto !important;
          }
    
          .slider {
            margin-top: 10vh;
            display: flex;
            /* align-items: flex-end; */
            width: auto;
            /* height: 700px; */
            transition: 0.5s ease-in-out;
          }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Slider</title>
      </head>
      <body>
        <div id="lookbook" data-tab-content class="black-text">
          <div class="lookbook-nav">
            <button id="left">←</button>
            <button id="right">→</button>
          </div>
          <div class="lookbook">
            <div class="slider" id="slider">
              <img src="https://picsum.photos/600/360" alt="" />
              <img src="https://picsum.photos/600/360" alt="" />
              <img src="https://picsum.photos/600/360" alt="" />
              <img src="https://picsum.photos/600/360" alt="" />
              <img src="https://picsum.photos/600/360" alt="" />
              <img src="https://picsum.photos/600/360" alt="" />
            </div>
          </div>
        </div>
      </body>
    </html>

    我只是让一个导航箭头的工作,但应该是相同的事情只是在相反的顺序,你也不必担心计数器,因为它会检测多少图像,你在滑块内。