如何向此Angular轮播添加无限滚动? [英] How can I add infinite scrolling to this Angular carousel?

查看:81
本文介绍了如何向此Angular轮播添加无限滚动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我关注了这篇很棒的文章,演示了如何使用Angular中的两个指令和一个组件来制作一个简单的轮播.

I followed this fantastic article, that demonstrates how to make a simple carousel with the use of two directives and one component in Angular.

功能集非常有限,并且不包含我要添加的"无限滚动"模式.

The feature set is very limited, and does not include an 'infinite scrolling' mode, which I would like to add.

'无限滚动'"-我的意思是类似jQuery的内容:

By 'inifinite scroll' - I mean something like this jQuery equivalent:

var carousel = $('#carousel'),
  threshold = 150,
  slideWidth = 500,
  dragStart,
  dragEnd;

$('#next').click(function() {
  shiftSlide(-1)
})
$('#prev').click(function() {
  shiftSlide(1)
})

carousel.on('mousedown', function() {
  if (carousel.hasClass('transition')) return;
  dragStart = event.pageX;
  $(this).on('mousemove', function() {
    dragEnd = event.pageX;
    $(this).css('transform', 'translateX(' + dragPos() + 'px)')
  })
  $(document).on('mouseup', function() {
    if (dragPos() > threshold) {
      return shiftSlide(1)
    }
    if (dragPos() < -threshold) {
      return shiftSlide(-1)
    }
    shiftSlide(0);
  })
});

function dragPos() {
  return dragEnd - dragStart;
}

function shiftSlide(direction) {
  if (carousel.hasClass('transition')) return;
  dragEnd = dragStart;
  $(document).off('mouseup')
  carousel.off('mousemove')
    .addClass('transition')
    .css('transform', 'translateX(' + (direction * slideWidth) + 'px)');
  setTimeout(function() {
    if (direction === 1) {
      $('.slide:first').before($('.slide:last'));
    } else if (direction === -1) {
      $('.slide:last').after($('.slide:first'));
    }
    carousel.removeClass('transition')
    carousel.css('transform', 'translateX(0px)');
  }, 700)
}

$carousel-width: 600px;
$carousel-height: 300px;
body {
  background: #333;
  color: #fff;
  font-size: 22pt;
  text-align: center;
  font-family: 'Teko';
  letter-spacing: 0.15em;
}

body * {
  -webkit-user-select: none
}

.wrap {
  position: relative;
  width: $carousel-width;
  height: 300px;
  margin: 0 auto;
  box-shadow: 7px 7px 5px 0px rgba(0, 0, 0, 0.25);
}

.window {
  overflow: hidden;
  position: relative;
  background: #222;
}

#carousel {
  width: 10000px;
  position: relative;
  top: 0;
  left: -450px;
}

.slide {
  height: 300px;
  width: 500px;
  cursor: pointer;
  float: left;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.slide#b1 {
  background: #556270
}

.slide#b2 {
  background: #4ECDC4
}

.slide#b3 {
  background: #9CE462
}

.slide#b4 {
  background: #FF6B6B
}

.slide#b5 {
  background: #C44D33
}

#prev,
#next {
  cursor: pointer;
  position: absolute;
  bottom: -40px;
  font-size: 14pt;
}

#prev {
  left: 0
}

#next {
  right: 0
}

.transition {
  transition: .7s;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>INFINITE CAROUSEL</h1>
<div class="wrap">
  <div class="window">
    <div id="carousel">
      <span class="slide" id="b1">SLIDE-1</span>
      <span class="slide" id="b2">SLIDE-2</span>
      <span class="slide" id="b3">SLIDE-3</span>
      <span class="slide" id="b4">SLIDE-4</span>
      <span class="slide" id="b5">SLIDE-5</span>
    </div>
  </div>
  <span id="prev">PREV</span>
  <span id="next">NEXT</span>
</div>

(轮播可以在各个方向上无限滚动,同时保持幻灯片的正确顺序)

(the carousel can be infinitely scrolled in each direction whilst keeping the correct order of the slides)

我尝试了多种添加此功能的方法,但都没有成功,这是我尝试过(后来被删除)的:

I have tried a number of approaches to add this feature and none have succeeded, what I've tried (and subsequently deleted):

  • 动态地在当前查看的子集的任一侧添加和删除大块幻灯片-即,如果轮播中包含3张幻灯片,我将在原始`1-2-3 1-2-3的任一侧复制它们,并且然后在用户滚动时添加/删除块.这几乎行得通,唯一的问题是,Angular在删除块并像疯了似的旋转旋转木马时感到困惑,因为它仍然引用了已不存在的幻灯片编号.

  • Dynamically adding and removing chunks of slides either side of the currently viewed subset - i.e. if the carousel contained 3 slides I would duplicate them either side of the original `1-2-3 1-2-3, and then add/remove chunks as the user scrolls. This almost worked, the only problem was that Angular got confused when removing chunks and spun the carousel like mad, because it still had a reference to a slide number that no longer existed.

动态添加和删除单个幻灯片,类似于上述方法.同样的问题.

Dynamically adding and removing single slides, similar to the above approach. Same issue.

直接向上复制幻灯片几百次.这种方法有效,但显然表现不佳,而且似乎很愚蠢.

Straight up duplicating the slides hundreds of times. This works but is obviously horribly un-performant and seems dumb.

这是一个 stackblitz显示我到目前为止所拥有的.

推荐答案

已更新 (在我们排在最后一个但又在第二个滑块中时,在对queryList进行重新排序之前)

Updated (before I reorder the queryList when we are in the last but one and in the second slider)

有一种解决方法.关键是重新排列QueryList的顺序,并在最后一个(上一个之前)或第一个(上一个之前)时更改currentSlide

there're a work-around. The key is reorder the QueryList and change the currentSlide when you're in the last (before make a next) or the first one (before make a prev)

首先将功能transitionCarrousel更改为允许在0秒内进行动画"

First change the function transitionCarrousel to allow an "animate" in 0 seconds

  private buildAnimation(offset, time: any) {
    return this.builder.build([
      animate(time == null ? this.timing : 0, 
          style({ transform: `translateX(-${offset}px)` }))
    ]);
  }

next和prev的功能类似

The functions next and prev becomes like

next() {
    //if we are in the last 
    if (this.currentSlide + 1 == this.items.length) {
      //reorder the QueryList, 
      let arr = this.items.toArray();
      let first = arr.shift();  //remove the first element
      arr = arr.concat([first]);  //Concat at last of the array
      this.items.reset(arr);
      this.currentSlide--;  //less currentSlide
      this.transitionCarousel(0); //execute the animation in 0 seconds
    }
    this.currentSlide = (this.currentSlide + 1) % this.items.length;
    this.transitionCarousel(null);
  }

  prev() {
    //If we are in the first one
    if (this.currentSlide  == 0) {
      let arr = this.items.toArray();
      let last = arr.pop();  //remove the last element
      arr = [last].concat(arr); //create an array with the last element+arr
      this.items.reset(arr);
      this.currentSlide++;  //change the currentSlide
      this.transitionCarousel(0);  //execute the animation in 0 seconds
    }
    this.currentSlide =
      (this.currentSlide - 1 + this.items.length) % this.items.length;
    this.transitionCarousel(null);
  }

您可以在 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆