Bootstrap Slides在使用角度6的多项旋转木马时滞后

问题描述 投票:9回答:2

我的问题是我使用Angular 6,Bootstrap v4和jQuery作为多项旋转木马。如果我在旋转木马上有[1,2,3,4,5,6]这样的数据,则必须显示[1,2,3]。按下下一步后,它必须显示[4,5,6]。

到目前为止,我实现了这个问题。只有第一张活动卡片正在移动,并且还存在滞后,并且前一个和下一个按钮不可见。请检查Stackblitz文件,您将了解该问题

这是我在Stackblitz的工作

https://stackblitz.com/edit/angular-jvr6dh

HTML代码

<div class="container">
  <div id="dataInfo">
      <h2>Information</h2>
      <div id="myCarousel" class="carousel slide" data-ride="carousel">
          <div class="carousel-inner row w-100 mx-auto">
            <div class="carousel-item col-md-4 active">
              <div class="card">
                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap">
                <div class="card-body">
                  <h4 class="card-title">Card 1</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"><div class="card-body">
                  <h4 class="card-title">Card 2</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"><div class="card-body">
                  <h4 class="card-title">Card 3</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"><div class="card-body">
                  <h4 class="card-title">Card 4</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"> <div class="card-body">
                  <h4 class="card-title">Card 5</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"><div class="card-body">
                  <h4 class="card-title">Card 6</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
            <div class="carousel-item col-md-4">
              <div class="card">

                <img class="card-img-top img-fluid" src="https://images.freeimages.com/images/large-previews/85a/daisy-s-1375598.jpg"  width="100" height="100" alt="Card image cap"><div class="card-body">
                  <h4 class="card-title">Card 7</h4>
                  <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                  <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
                </div>
              </div>
            </div>
          </div>
          <a class="carousel-control-prev" href="#myCarousel" role="button" data-slide="prev">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="sr-only">Previous</span>
          </a>
          <a class="carousel-control-next" href="#myCarousel" role="button" data-slide="next">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="sr-only">Next</span>
          </a>
        </div>

  </div>


</div>

。 ts代码:

$("#myCarousel").on("slide.bs.carousel", function(e) {
      var $e = $(e.relatedTarget);
      var idx = $e.index();
      var itemsPerSlide = 3;
      var totalItems = $(".carousel-item").length;

      if (idx >= totalItems - (itemsPerSlide - 1)) {
        var it = itemsPerSlide - (totalItems - idx);
        for (var i = 0; i < it; i++) {
          // append slides to end
          if (e.direction == "left") {
            $(".carousel-item")
              .eq(i)
              .appendTo(".carousel-inner");
          } else {
            $(".carousel-item")
              .eq(0)
              .appendTo($(this).find(".carousel-inner"));
          }
        }
      }
    });
  }

.scss代码

  .carousel-inner .active,
.carousel-inner .active + .carousel-item,
.carousel-inner .active + .carousel-item + .carousel-item {
  display: block;
}

.carousel-inner .carousel-item.active:not(.carousel-item-right):not(.carousel-item-left),
.carousel-inner .carousel-item.active:not(.carousel-item-right):not(.carousel-item-left) + .carousel-item,
.carousel-inner .carousel-item.active:not(.carousel-item-right):not(.carousel-item-left) + .carousel-item + .carousel-item {
  transition: none;
}

.carousel-inner .carousel-item-next,
.carousel-inner .carousel-item-prev {
  position: relative;
  transform: translate3d(0, 0, 0);
}

.carousel-inner .active.carousel-item + .carousel-item + .carousel-item + .carousel-item {
  position: absolute;
  top: 0;
  right: -33.3333%;
  z-index: -1;
  display: block;
  visibility: visible;
}

/* left or forward direction */
.active.carousel-item-left + .carousel-item-next.carousel-item-left,
.carousel-item-next.carousel-item-left + .carousel-item,
.carousel-item-next.carousel-item-left + .carousel-item + .carousel-item,
.carousel-item-next.carousel-item-left + .carousel-item + .carousel-item + .carousel-item {
  position: relative;
  transform: translate3d(-100%, 0, 0);
  visibility: visible;
}

/* farthest right hidden item must be abso position for animations */
.carousel-inner .carousel-item-prev.carousel-item-right {
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  display: block;
  visibility: visible;
}

/* right or prev direction */
.active.carousel-item-right + .carousel-item-prev.carousel-item-right,
.carousel-item-prev.carousel-item-right + .carousel-item,
.carousel-item-prev.carousel-item-right + .carousel-item + .carousel-item,
.carousel-item-prev.carousel-item-right + .carousel-item + .carousel-item + .carousel-item {
  position: relative;
  transform: translate3d(100%, 0, 0);
  visibility: visible;
  display: block;
  visibility: visible;
}
javascript jquery angular twitter-bootstrap typescript
2个回答
6
投票

根据您的示例代码,看起来简化Bootstrap代码本身使用标准轮播是最好的方法。下面的链接是您提供的示例的一个分支,其中包含以下更改:

https://stackblitz.com/edit/angular-yaevix

  • 删除了prev / next / etc上的所有自定义DOM操作。从你的JavaScript,所以它使用Bootstrap轮播组件来做所有事情
  • 删除了试图调整卡片动画和位置的CSS
  • 添加了next / prev图标的快速和脏位置(您可以根据需要设置样式)

您将每张卡片设置为轮播项目,但在您的描述中,您希望一次分页3。这里的正确方法是每三张卡片有一个旋转木马项目。见下面的例子

带有多张卡片的一个轮播项目的示例:

<div id="myCarousel" class="carousel slide" data-ride="carousel">
    <div class="carousel-inner">
        <div class="carousel-item active">
            <div class="row">
                <div class="col-md-4">
                    <div class="card">Card 1</div>
                </div>
                <div class="col-md-4">
                    <div class="card">Card 2</div>
                </div>
                <div class="col-md-4">
                    <div class="card">Card 3</div>
                </div>
            </div>
        </div>
        <div class="carousel-item active">
            <div class="row">
                <div class="col-md-4">
                    <div class="card">Card 4</div>
                </div>
                <div class="col-md-4">
                    <div class="card">Card 5</div>
                </div>
                <div class="col-md-4">
                    <div class="card">Card 6</div>
                </div>
            </div>
        </div>
        <div class="carousel-item">
            <div class="row">
                <div class="col-md-4">
                    <div class="card">Card 7</div>
                </div>
            </div>
        </div>
    </div>
</div>

4
投票

您可能会发现编写自己的轮播行为更容易,并删除对jquery的依赖。您仍然可以使用Bootstrap来设置样式。

我们还可以使用Angular动画来保留动画行为。 (请注意,这是我第一次使用Angular动画,因此可能有更简洁的方法)

第一步是创建一个指令,它处理next / prev行为:

  @Input() animationDuration = 500;

  private slideLeft: AnimationFactory;
  private slideRight: AnimationFactory;
  private slideInLeft: AnimationFactory;
  private slideInRight: AnimationFactory;

  constructor(private el: ElementRef, private _builder: AnimationBuilder) {
  }

  ngOnInit() {
    this.slideLeft = this._builder.build([
      style({ transform: 'translateX(0)' }),
      animate(this.animationDuration, style({ transform: 'translateX(-100%)' })),
      style({ transform: 'translateX(0)' }),
    ]);

    this.slideRight = this._builder.build([
      style({ transform: 'translateX(0)' }),
      animate(this.animationDuration, style({ transform: 'translateX(100%)' })),
      style({ transform: 'translateX(0)' }),
    ]);

    this.slideInLeft = this._builder.build([
      style({ transform: 'translateX(100%)', right: 0 }),
      animate(this.animationDuration, style({ transform: 'translateX(0)' })),
      style({ right: 'initial' })
    ]);

    this.slideInRight = this._builder.build([
      style({ transform: 'translateX(-100%)', left: 0 }),
      animate(this.animationDuration, style({ transform: 'translateX(0)' })),
      style({ left: 'initial' })
    ]);
  }

  next(steps) {
      let active = this.el.nativeElement.querySelectorAll('.carousel-item.active');
      let inactive = this.el.nativeElement.querySelector('.carousel-item:not(.active)');
      // Start the animation
      this.animateAll(active, this.slideLeft);
      // Start the slide in animation for the next element
      this.preMoveElement(inactive);
      this.slideInLeft.create(inactive).play();

      setTimeout(() => {
        // Move the last element to start and make it active.
        active = this.el.nativeElement.querySelectorAll('.carousel-item.active');
        inactive = this.el.nativeElement.querySelector('.carousel-item:not(.active)');
        active[0].classList.remove('active');
        this.el.nativeElement.insertBefore(active[0], null);
        inactive.classList.add('active');
        if (steps && steps - 1 > 0) {
          this.next(steps - 1);
        }
      }, this.animationDuration);
   // }
  }

  prev(steps) {
    const active = this.el.nativeElement.querySelectorAll('.carousel-item.active');
    const children = this.el.nativeElement.children;
    const lastChild = children[children.length - 1];
    // Start the animation
    this.animateAll(active, this.slideRight);
    // Start the slide in animation for the next element
    this.preMoveElement(lastChild);
    this.slideInRight.create(lastChild).play();


    setTimeout(() => {
      // Remove the active class
      const lastActive = active[active.length - 1];
      lastActive.classList.remove('active');
      // Move the last element to the start, and make it active
      this.el.nativeElement.insertBefore(lastChild, children[0]);
      lastChild.classList.add('active');
      if (steps && steps - 1 > 0) {
        this.prev(steps - 1);
      }
    }, this.animationDuration);
  }

  private animateAll(elements: any[], animation: AnimationFactory) {
    elements.forEach(element => {
      animation.create(element).play();
    });
  }

  private preMoveElement(element) {
    element.style.display = 'block';
    element.style.position = 'absolute';
    setTimeout(() => {
      element.style = null;
    }, this.animationDuration);
  }

然后,您可以从HTML访问prevnext函数:

更改carousel-inner元素,如下所示:

<div class="carousel-inner row w-100 mx-auto" #cara="Carousel">

然后我们可以使用cara变量来访问公共函数:

  <a class="carousel-control-prev" role="button" (click)="cara.prev(3)">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="carousel-control-next" role="button" (click)="cara.next(3)">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>

最后,将carousel-items的3标记为.active,以便同时显示3。

Here is a StackBlitz demo

© www.soinside.com 2019 - 2024. All rights reserved.