Угловой гладкий скруток не работает при использовании анимации

Я новичок в Angular и попытался настроить smoothScroll: https://github.com/kavil/ng2SmoothScroll

У меня есть вид, подобный этому:

<piiick-one smoothScroll offset="10" [scrollIf]="step === 1"></piiick-one>
<piiick-two *ngIf="max >= 2" smoothScroll offset="10" [scrollIf]="step === 2"></piiick-two>
<piiick-three *ngIf="max >= 3" smoothScroll offset="10" [scrollIf]="step === 3"></piiick-three>
<piiick-results *ngIf="max >= 4" smoothScroll offset="10" [scrollIf]="step === 4"></piiick-results>

И компонент настраивается следующим образом:

export class StepsComponent implements DoCheck {
  step: number = 0;
  max: number = 0;
  private path: string;

  constructor(
    private route: ActivatedRoute
  ) {
    this.route.params.subscribe(params => this.path = params.path)
  }

  ngDoCheck() {
    switch (this.path) {
      case 'one': this.changeStep(1); break;
      case 'two': this.changeStep(2); break;
      case 'three': this.changeStep(3); break;
      case 'results': this.changeStep(4); break;
      default: this.changeStep(0); break;
    }    
  }

  private changeStep(step) {
    var current = this.step;

    this.step = step;
    if (step > current) {
      this.max = step;
    }
  }
}

, что должно произойти, заключается в том, что при вызове маршрута /steps/three он будет smoothScroll в div с id равен трем. Это работало, пока я не включил анимацию перехода на страницу.

Теперь у меня есть этот код в моем app.component:

import { Component } from '@angular/core';
import { query, style, animate, trigger, transition, group } from '@angular/animations';

const routerTransition = trigger('routerTransition', [
  transition('* => home', [
    query(':enter, :leave', style({ position: 'fixed', width:'100%' })
      , { optional: true }),
    group([
      query(':enter', [
        style({ transform: 'translateX(-100%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
      ], { optional: true }),
      query(':leave', [
        style({ transform: 'translateX(0%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))
      ], { optional: true }),
    ])
  ]),
  transition('* => steps', [
    group([
      query(':enter, :leave', style({ position: 'fixed', width:'100%' })
      , { optional: true }),
      query(':enter', [
        style({ transform: 'translateX(100%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
      ], { optional: true }),
      query(':leave', [
        style({ transform: 'translateX(0%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))
      ], { optional: true }),
    ])
  ])
])

@Component({
  selector: 'piiick-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  animations: [routerTransition]
})
export class AppComponent {
  prepareRouteTransition(outlet) {
    return outlet.activatedRouteData.state;
  }
}

, когда animations закомментирован, smoothScroll работает; но когда он включен, smoothScroll не запускается. Кто-нибудь знает, почему?

2
задан 13 August 2018 в 14:24

1 ответ

Думаю, я нашел ответ на этот вопрос. Если вы нашли сообщение, в котором кто-то показывал, как вы можете запускать события после завершения анимации. Поэтому я создал AnimationService следующим образом:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class AnimationService {
  private animatingSubject = new Subject<boolean>();

  animating = this.animatingSubject.asObservable();

  constructor() { }

  loading(state: boolean) {
    this.animatingSubject.next(state);
  }
}

, который используется для установки состояния анимации. Я создал компонент AnimationService , который был примерно таким:

<div [@routerTransition]="prepareRouteTransition(outlet)" (@routerTransition.start)="handleStart()" (@routerTransition.done)="handleDone()">
  <router-outlet #outlet="outlet"></router-outlet>
</div>

, и это было добавлено в мой App.Component следующим образом:

<piiick-header></piiick-header>
<piiick-animations></piiick-animations>
<piiick-spinner></piiick-spinner>

Код компонента выглядит так:

import { Component } from '@angular/core';
import { query, style, animate, trigger, transition, group } from '@angular/animations';

import { AnimationService } from '../../core/services/animation.service';

const routerTransition = trigger('routerTransition', [
  transition('* => home', [
    query(':enter, :leave', style({ position: 'fixed', width:'100%' })
      , { optional: true }),
    group([
      query(':enter', [
        style({ transform: 'translateX(-100%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
      ], { optional: true }),
      query(':leave', [
        style({ transform: 'translateX(0%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))
      ], { optional: true }),
    ])
  ]),
  transition('* => steps', [
    group([
      query(':enter, :leave', style({ position: 'fixed', width:'100%' })
      , { optional: true }),
      query(':enter', [
        style({ transform: 'translateX(100%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
      ], { optional: true }),
      query(':leave', [
        style({ transform: 'translateX(0%)' }),
        animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))
      ], { optional: true }),
    ])
  ])
])

@Component({
  selector: 'piiick-animations',
  templateUrl: './animations.component.html',
  styleUrls: ['./animations.component.scss'],
  animations: [routerTransition]
})
export class AnimationsComponent {
  constructor(private animationService: AnimationService) { }

  prepareRouteTransition(outlet) {
    return outlet.activatedRouteData.state;
  }

  handleStart(e) {
    this.animationService.loading(true);
  }

  handleDone(e) {
    this.animationService.loading(false);
  }
}

Как вы можете видеть, при запуске анимации он обновляет App.Component и устанавливает для свойства анимации значение true, когда он завершает анимацию, он просто обновляет службу еще раз и устанавливает для свойства значение false.

Теперь было просто заставить его работать с smoothScroll. Сначала я не мог заставить это работать, тогда я понял, что это была не просто анимация, которую я должен был ждать, но и контент; поэтому я добавил свойство StepsComponent, которое было обновлено после инициализации представления.

Я обновил HTML до этого:

<div *ngIf="scrollIf">
    <piiick-one smoothScroll offset="10" [scrollIf]="step === 1"></piiick-one>
    <piiick-two *ngIf="max >= 2" smoothScroll offset="10" [scrollIf]="step === 2"></piiick-two>
    <piiick-three *ngIf="max >= 3" smoothScroll offset="10" [scrollIf]="step === 3"></piiick-three>
    <piiick-results *ngIf="max >= 4" smoothScroll offset="10" [scrollIf]="step === 4"></piiick-results>

    <piiick-navigation></piiick-navigation>
</div>

, а затем изменил код на это: [ ! d13]

export class StepsComponent implements DoCheck, AfterViewInit {
  step: number = 0;
  max: number = 0;
  scrollIf: boolean = false;

  private path: string;
  private afterViewInit: boolean;
  private viewAnimating: boolean;

  constructor(
    private route: ActivatedRoute,
    private animationService: AnimationService
  ) {
    this.route.params.subscribe(params => this.path = params.path);
    this.animationService.animating.subscribe(animating => this.viewAnimating = animating);
  }

  ngAfterViewInit() {
    this.afterViewInit = true;
  }

  ngDoCheck() {
    if (this.afterViewInit) {
      switch (this.path) {
        case 'one': this.changeStep(1); break;
        case 'two': this.changeStep(2); break;
        case 'three': this.changeStep(3); break;
        case 'results': this.changeStep(4); break;
        default: this.changeStep(0); break;
      }
      this.scrollIf = this.afterViewInit && !this.viewAnimating;
    }
  }

  private changeStep(step) {
    var current = this.step;

    this.step = step;
    if (step > current) {
      this.max = step;
    }
  }
}

, так что теперь работают анимация и smoothScroll. Единственная проблема, с которой я сталкиваюсь, заключается в том, что представление не отображается до тех пор, пока оно не будет инициализировано. Я не уверен, что это проблема.

0
ответ дан 15 August 2018 в 17:03

Другие вопросы по тегам:

Похожие вопросы: