如何制作一个无限的 JS 轮播(无穷大问题)

Posted

技术标签:

【中文标题】如何制作一个无限的 JS 轮播(无穷大问题)【英文标题】:How to make an infinite JS Carousel ( infinity problem) 【发布时间】:2020-02-03 05:04:43 【问题描述】:

试图制作一个无限旋转木马,它会以我选择的位置为中心。 轮播应该循环播放,目前我只在一侧实现了效果,我的主要问题是过渡是可见的。

我需要达到的效果是,当您单击轮播时,循环是无限的,但您看不到从一端到另一端的闪烁,我对 Web 开发相对较新,因此将不胜感激。 提前致谢!

html

      <div class="content__bottom">
    <div class="service__block" data-name="instagram" data-order="1">
      <i class="service__block--icon fab fa-instagram"></i>
      <h5 class="service__block--title">אינסטגרם</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="facebook" data-order="2">
      <i class="service__block--icon fab fa-facebook-f"></i>
      <h5 class="service__block--title">פייסבוק</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="youtube" data-order="3">
      <i class="service__block--icon fab fa-youtube"></i>
      <h5 class="service__block--title">יוטיוב</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="twitch" data-order="4">
      <i class="service__block--icon fab fa-twitch"></i>
      <h5 class="service__block--title">טוויץ</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="twitter" data-order="5">
      <i class="service__block--icon fab fa-twitter"></i>
      <h5 class="service__block--title">טוויטר</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="pinterest" data-order="6">
      <i class="service__block--icon fab fa-pinterest"></i>
      <h5 class="service__block--title">פינטרסט</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="soundcloud" data-order="7">
      <i class="service__block--icon fab fa-soundcloud"></i>
      <h5 class="service__block--title">סאונדקלאוד</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="spotify" data-order="8">
      <i class="service__block--icon fab fa-spotify"></i>
      <h5 class="service__block--title">ספוטיפי</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="telegram" data-order="9">
      <i class="service__block--icon fab fa-telegram-plane"></i>
      <h5 class="service__block--title">טלגרם</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
    <div class="service__block" data-name="tumblr" data-order="10">
      <i class="service__block--icon fab fa-tumblr"></i>
      <h5 class="service__block--title">טאמבלר</h5>
      <i class="service__block--arrow fas fa-chevron-circle-up"></i>
    </div>
  </div>

SCSS:

    * 
  margin: 0;
  padding: 0;

*,
*::before,
*::after 
  box-sizing: inherit;


html 
  box-sizing: border-box;
  font-size: 62.5%; // 1rem = 10px, 10px/16px = 62.5%


body 
  max-height: 100vh;
  font-family: 'Arimo', sans-serif;
  font-weight: 400;
  line-height: 1.6;
  background-color: #f8f8f8;
  // overflow: hidden;
  overflow-x: hidden;


.content__bottom 
  margin-top: 3%;
    width: 100vw;
    height: auto;
    padding: 2% 2%;
    display: flex;


.service__block 
      cursor: pointer;
      position: absolute;
      width: 210px;
      height: 200px;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 3rem 5rem;
      border-radius: 3.5rem;
      border: 1px solid transparent;
      background-color: white;
      box-shadow: 5px 5px 20px rgba($color: black, $alpha: 0.05);
      transition: all 0.5s;

      &[data-order='0'] 
        right: -17.5%;
        display: none;
        opacity: 0;
        z-index: -1;
        transition: none;

      
      &[data-order='1'] 
        right: -5.5%;

      
      &[data-order='2'] 
        right: 6.5%;

      
      &[data-order='3'] 
        right: 18.5%;

      
      &[data-order='4'] 
        right: 30.5%;

      
      &[data-order='5'] 
        right: 42.5%;

      
      &[data-order='6'] 
        right: 54.5%;

      
      &[data-order='7'] 
        right: 66.5%;

      
      &[data-order='8'] 
        right: 78.5%;

      
      &[data-order='9'] 
        right: 90.5%;

      
      &[data-order='10'] 
        right: 102.5%;

      
      &[data-order='11'] 
        right: 114.5%;
        display: none;
        z-index: -1;
        transition: none;

      
      &--icon 
        color: #adadad;
        font-size: 7rem;
        margin-bottom: 3rem;
        transition: all 0.5s;

      
      &--title 
        color: #adadad;
        font-size: 2.5rem;
        transition: all 0.5s;
        font-weight: 400;


      
      &--arrow 
        color: #4d48a8;
        font-size: 3rem;
        display: none;
        opacity: 0;
        transform: translateY(-5rem);
        transition: all 0.5s;
        cursor: pointer;

      
    
    .service__block:hover 
      .service__block--icon,
      .service__block--title 
        color: #707070;
      
    
    .selected 
      height: 250px;
      border: 1px solid #4d48a8;

      .service__block--title 
        color: #4d48a8;
        margin-bottom: 2rem;

      
      .service__block--icon 
        color: #4d48a8;
      
      .service__block--arrow 
        display: block;
        transform: translateY(0);
        opacity: 1;
      
      &:hover 
        .service__block--title 
          color: #4d48a8;
        
        .service__block--icon 
          color: #4d48a8;
        
      
    

JS:

const serviceList = document.querySelectorAll('.service__block');

serviceList.forEach(service => 
  service.addEventListener('click', () => 
    markSelectedService(service);
    checkDistance(service);
    moveService(checkDistance(service));
  );
);

//Adds the class to the clicked service
function markSelectedService(service) 
  removeSelectedClass();
  service.classList.add('selected');


//Removes the selected class from all the services
function removeSelectedClass() 
  serviceList.forEach(service => 
    service.classList.remove('selected');
  );


function moveServices(service) 
  //Check Service distance from center
  checkDistance(service);
  //Check if service is outside view

  //Check last position of serviceList
  //If service is outside view disable display
  //Move service to end of the serviceList
  //Enable visiblity


//Check distance from center
function checkDistance(service) 
  let distance = service.dataset.order - 4;
  return distance;


//Check if service is outside view
//Services 1 to 9 are visible the rest are outside the view
function checkIfVisible() 
  serviceList.forEach(service => 
    if (
      parseInt(service.dataset.order) > 0 &&
      parseInt(service.dataset.order) < 11
    ) 
      service.style.display = 'flex';
     else 
      service.style.display = 'none';
    
  );


//Move the service 1 by 1 n times
function moveService(distance) 
  if (distance > 0) 
    for (var i = 0; i < distance; i++) 
      serviceList.forEach(service => 
        service.dataset.order = parseInt(service.dataset.order) - 1;

        if (
          parseInt(service.dataset.order) === 0 &&
          service.dataset.name == 'instagram'
        ) 
          service.dataset.order = 11;
          service.dataset.order = checkServiceListLastPosition();
         else if (parseInt(service.dataset.order) === 0) 
          service.dataset.order = 11;
          service.dataset.order = checkServiceListLastPosition() + 1;
        
      );
    
   else if (distance < 0) 
    distance = distance * -1;
    for (var i = 0; i < distance; i++) 
      serviceList.forEach(service => 
        service.dataset.order = parseInt(service.dataset.order) + 1;
      );
    
  


//Check last position
function checkServiceListLastPosition() 
  lastPosition = 0;
  serviceList.forEach(service => 
    if (
      parseInt(service.dataset.order) > lastPosition &&
      parseInt(service.dataset.order) !== 11
    ) 
      lastPosition = parseInt(service.dataset.order);
    
  );
  console.log(lastPosition);
  return lastPosition;

当前状态的代码笔: https://codepen.io/tomyshoam/pen/yLLLYyQ

【问题讨论】:

那里有很多代码要grek!问题的关键是在移动发生之前禁用正在移动的元素上的过渡 css。这将涉及添加一个类似于 transition: none; 的 CSS 类 @jonny 我已经有过渡:无;在第一个和最后一个项目上禁用过渡,但它仍然弹出 【参考方案1】:

您可以在当前 .service__block 上方创建另一个 css 块,以覆盖 data-order 1 块的转换行为。

.service__block 
  &[data-order='1'] 
    right: -17.5%;
    display: none;
    opacity: 0;
    z-index: -1;
    transition: none;
  

【讨论】:

以上是关于如何制作一个无限的 JS 轮播(无穷大问题)的主要内容,如果未能解决你的问题,请参考以下文章

启用环绕的线性轮播

Vue在同一个页面制作多个轮播图

如何在 C++ 中检查无限和不确定的值?

CSS 实现无限循环轮播效果,根本不需要 JS

Bootstrap轮播图的切换按钮如何制作?

如何用Bootstrap制作轮播图