简体   繁体   English

如何用@ angular / animations动画ScrollTop?

[英]How to animate ScrollTop with @angular/animations?

I'm trying to replicate this animation from Material.io: 我正在尝试从Material.io复制此动画:

卡片动画

To just navigate the height like the click on the first card in the example above is simple. 要像上面示例中第一张卡片上的点击一样导航高度很简单。 Just animate height attribute. 只是动画高度属性。 The problem is with the click on the second card where it then pushes the other cards away. 问题在于点击第二张卡然后将其他卡推开。

One solution to this is to use scroll to emulate the effect that things get pushed away. 对此的一个解决方案是使用滚动来模拟事物被推开的效果。 So when you click on the item, it both makes it taller by animating the height, but also scroll the view at the same time. 因此,当您单击该项目时,它通过设置高度动画使其更高,但同时也滚动视图。

My problem: I can't seem to figure out how to animate scrolls with @angular/animations . 我的问题:我似乎无法弄清楚如何使用@angular/animations动画滚动。 I can't use style({ scrollTop: 100 }) , it only allows for CSS attributes according to the documentation . 我不能使用style({ scrollTop: 100 }) ,它只允许根据文档的 CSS属性。

How do I achieve this? 我该如何实现这一目标? It would be nice if I could do it as part of the animate() animation for maintenance reasons (To keep the whole animation in 1 location in the code), but if it's only possible with a separate method I guess that would be acceptable as well. 如果我可以将其作为animate()动画的一部分用于维护原因(将整个动画保存在代码中的1个位置),那将是很好的,但如果它只能使用单独的方法,我猜这是可以接受的好。

I managed to create this, using three Angular animations states : small , big and normal , corresponding to the height of the div : 我设法创建了这个,使用三个Angular动画状态: smallbignormal ,对应div的高度:

animations.ts animations.ts

Here, I used one state variable per div as an example, and I set the each of these states to normal by default. 在这里,我使用每个div的一个状态变量作为示例,并且我默认将这些状态中的每一个设置为正常 Then, depending on which div I click on, I toggle the states according to what we want to happen : making the div we click on bigger and the others smaller 然后,根据我点击的div,我根据我们想要发生的事情切换状态:使我们点击的div 更大而其他更小

export const expand = [
  trigger('expand', [
    state('big', style({
      'height': '200px'
    })),
    state('normal', style({
      'height': '100px'
    })),
    state('small', style({
      'height': '50px'
    })),
    transition('* => *', [group([
      animate(1000)
    ]
    )])
  ]),
]

app.component.ts app.component.ts

import { expand } from './animations';

@Component({
  ...
  animations: [expand]
})
export class AppComponent implements OnInit {
  expandState1 = 'normal';
  expandState2 = 'normal';
  expandState3 = 'normal';
  expandState4 = 'normal';
  expandState5 = 'normal';

  ngOnInit() {
    this.resetStates();
  }

  resetStates() {
    this.expandState1 = 'normal';
    this.expandState2 = 'normal';
    this.expandState3 = 'normal';
    this.expandState4 = 'normal';
    this.expandState5 = 'normal';
  }

  toggleShowDiv(divName: string) {
    if (divName === 'div1') {
      if (this.expandState1 === 'normal' || this.expandState1 === 'small') {
        this.setToBig([1]);
        this.setToSmall([2, 3, 4, 5]);
      } else if (this.expandState1 === 'big' || this.expandState1 === 'small') {
        this.resetStates();
      }
    } else if (divName === 'div2') {
      if (this.expandState2 === 'normal' || this.expandState2 === 'small') {
        this.setToBig([2]);
        this.setToSmall([1, 3, 4, 5]);
      } else if (this.expandState2 === 'big') {
        this.resetStates();
      }
    } else if (divName === 'div3') {
      if (this.expandState3 === 'normal' || this.expandState3 === 'small') {
        this.setToBig([3]);
        this.setToSmall([1, 2, 4, 5]);
      } else if (this.expandState3 === 'big') {
        this.resetStates();
      }
    } else if (divName === 'div4') {
      if (this.expandState4 === 'normal' || this.expandState4 === 'small') {
        this.setToBig([4]);
        this.setToSmall([1, 2, 3, 5]);
      } else if (this.expandState4 === 'big') {
        this.resetStates();
      }
    } else if (divName === 'div5') {
      if (this.expandState5 === 'normal' || this.expandState5 === 'small') {
        this.setToBig([5]);
        this.setToSmall([1, 2, 3, 4]);
      } else if (this.expandState5 === 'big') {
        this.resetStates();
      }
    }
  }

  setToSmall(choices: any) {
    for (let i = 0; i < choices.length; i++) {
      switch (choices[i]) {
        case 1:
          this.expandState1 = 'small';
          break;
        case 2:
          this.expandState2 = 'small';
          break;
        case 3:
          this.expandState3 = 'small';
          break;
        case 4:
          this.expandState4 = 'small';
          break;
        case 5:
          this.expandState5 = 'small';
          break;
        default:
          break;
      }
    }
  }

  setToBig(choices: any) {
    for (let i = 0; i < choices.length; i++) {
      switch (choices[i]) {
        case 1:
          this.expandState1 = 'big';
          break;
        case 2:
          this.expandState2 = 'big';
          break;
        case 3:
          this.expandState3 = 'big';
          break;
        case 4:
          this.expandState4 = 'big';
          break;
        case 5:
          this.expandState5 = 'big';
          break;
        default:
          break;
      }
    }
  }
}

And here is the corresponding template : 这是相应的模板:

Each div has the reference to the animation trigger [@expand] and its state. 每个div都有对动画触发器[@expand]及其状态的引用。

<div class="wrapper scrollableDiv">
  <div [@expand]="expandState1" (click)="toggleShowDiv('div1')" class="content divA">THIS IS CONTENT DIV 1</div>
  <div [@expand]="expandState2" (click)="toggleShowDiv('div2')" class="content divA">THIS IS CONTENT DIV 2</div>
  <div [@expand]="expandState3" (click)="toggleShowDiv('div3')" class="content divA">THIS IS CONTENT DIV 3</div>
  <div [@expand]="expandState4" (click)="toggleShowDiv('div4')" class="content divA">THIS IS CONTENT DIV 4</div>
  <div [@expand]="expandState5" (click)="toggleShowDiv('div5')" class="content divA">THIS IS CONTENT DIV 5</div>
</div>

Here is a StackBlitz example I made for this : https://stackblitz.com/edit/angular-t47iyy 这是我为此制作的StackBlitz示例: https ://stackblitz.com/edit/angular-t47iyy

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM