angular:自动滚动元素

时间:2017-11-25 05:04:38

标签: css angular material

我想找到一种方法让列表中的项目顺利向上滚动,如果可能的话会产生动画效果。

以下是我的商品清单:https://plnkr.co/edit/nRhpyO71eHOaQTzOElFe?p=preview

<button (click)="prev()">Prev</button>
<button (click)="next()">Next</button>
<button (click)="autoplay()">Auto play</button>
<div>
  Current: {{current}}
</div>

<div class="wrapper">

  <mat-card *ngFor="let item of [0, 1, 2,3,4,5,6,7,8,9]"
  class="item" id="'item'+item"
  [ngClass]="item == current ? 'active' : ''"
   >
   This is item {{item}}
  </mat-card>

</div>

组件 -

export class CardOverviewExample {

  constructor(private elRef:ElementRef) {

  }

  current: number = 0;

  autoplay() {
    if (this.current < 9) {
     next();
    } else {
      this.current = 0;
    }
    setTimeout(() => this.autoplay(), 2000);
  }

  next() {
    this.current = this.current + 1;
    setTimeout(() => this.scrollCurrentIntoView);
  }
  prev() {
    this.current = this.current - 1;
    setTimeout(() => this.scrollCurrentIntoView);
  }
  scrollCurrentIntoView() {

    let id = '#item' + current;
    let el = this.elRef.nativeElement.querySelector(id);
    console.log("el: ", el);
    el.nativeElement.scrollIntoView({behavior: "smooth", block: "start", inline: "start"});
  }
}

既有移动到下一个元素的手动模式,也有自动模式,下一个项目在几秒钟内变为活动状态。要求是让当前活动元素始终位于顶部,但如果用户希望这样做,则仍然滚动列表并从列表中选择另一个项目。

我尝试使用scrollIntoView的行为:smooth。虽然它有效,但它有时会浮华,我正在寻找替代品。 (注意:scrollIntoView并不适用于plunker示例,但它适用于我的应用程序。)

我尝试了在https://stackoverflow.com/a/45367387/1893487建议的解决方案 - 模拟慢速滚动我尝试将scrollTop值设置为2s以上的不同增量。这样可行,但它仍然不顺畅。有时我看不到角度变化检测器显示中间状态。

我想知道是否有可能使用CSS translateY转换来实现滚动,因为这也应该更高效。建议实现滚动的替代机制。

1 个答案:

答案 0 :(得分:0)

你可以使用一点JS

function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
    return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
};

function elmYPosition(eID) {
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body) {
        node = node.offsetParent;
        y += node.offsetTop;
    } return y;
};

function smoothScroll(eID) {
    var startY = currentYPosition();
    var stopY = elmYPosition(eID);
    var distance = stopY > startY ? stopY - startY : startY - stopY;
    if (distance < 100) {
        scrollTo(0, stopY); return;
    }
    var speed = Math.round(distance / 75);
    if (speed >= 20) speed = 20;
    var step = Math.round(distance / 25);
    var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) {
        for ( var i=startY; i<stopY; i+=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > stopY) leapY = stopY; timer++;
        } return;
    }
    for ( var i=startY; i>stopY; i-=step ) {
        setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
        leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
    }
    return false;
};

然后将滚动更改为像这样的视图

scrollCurrentIntoView() {

let id = '#item' + current;
let el = this.elRef.nativeElement.querySelector(id);
console.log("el: ", el);
smoothScroll(el);

}