Ионная анимация пользовательских кнопок срабатывает на всех кнопках

#css #angular #ionic-framework #css-animations

#css #angular #ионный фреймворк #css-анимации

Вопрос:

Я пытаюсь реализовать анимированную кнопку избранного в приложении Ionic, и у меня возникает несколько проблем.

Кнопка работает, как и ожидалось, при нажатии, но она также запускает любую другую кнопку для воспроизведения анимации. Анимация также воспроизводится на всех кнопках при каждой загрузке страницы. Я подозреваю, что мой оператор ngClass для добавления активного класса каким-то образом запускается, когда страница загружает сообщения и снова, когда данные обновляются из наблюдаемого при добавлении избранного.

 <ion-button class="favourite" fill="clear" size="small" (click)="toggleFavourite( post, user.userId )">
   <ion-icon [ngClass]="{'active': post.favourites amp;amp; post.favourites[user.userId] ? true : false}" class="heart"></ion-icon>
</ion-button>
  

css:

 .heart {
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) scale(0.9);
    background: url('/assets/images/heart.png') no-repeat;
    background-position: 0 0;
    cursor: pointer;
    animation: fave-heart 1s steps(28);
}

.heart.active {
    background-position: -2800px 0;
    transition: background 1s steps(28);
}

@keyframes fave-heart {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: -2800px 0;
    }
}
  

Я провел еще несколько тестов и обнаружил, что анимация кнопок запускается каждый раз, когда я обновляю свою переменную posts. Сообщения возвращаются как наблюдаемые, поэтому они обновляются при каждой загрузке страницы, а также когда пользователь выбирает сообщение в избранном, чтобы я мог обновить кнопку. Тем не менее, я добавил кнопку, которая вызывает функцию getPosts() (ниже), и она также запускает анимацию при каждом нажатии.

 
<ion-button (click)="getPosts(limit)">click</ion-button>

getPosts(limit){
    return new Promise((resolve) => {
      this.postsService.getPosts(limit).subscribe(data => {
        this.posts = data.reverse()
        let key = data[data.length - 1].$key;
        if (this.lastId === key){
          this.hasMoreData = false;
        }
        resolve(data);
      });
    });
  }
  

Комментарии:

1. может быть, потому, что вы не помещаете анимацию в .active в свой css?

2. Похоже, что это работает, просто анимация происходит на каждой кнопке. Кнопка, на которую нажали, завершает анимацию и заканчивается сплошным сердцем, как и ожидалось. Остальные кнопки анимируются, а затем возвращаются к контуру сердца.

3. вместо этого вы могли бы использовать .heart:active . Javascript не требуется

4. Я не могу использовать:active, поскольку мне нужно изменить класс, чтобы при загрузке сообщений я мог изменять состояние кнопки в зависимости от того, была ли она в избранном или нет.

Ответ №1:

Я провел еще несколько исследований и нашел гораздо лучший способ сделать это. Этот способ использует анимацию Ionic 5, поэтому я могу настроить идентификатор элемента, на который был нажат, для воспроизведения анимации при выборе.

 amp;.heart {
   width: 100px;
   height: 100px;
   position: absolute;
   transform: scale(0.9);
   background: url('/assets/images/heart.png') no-repeat;
   background-position: 0 0;
   cursor: pointer;
}
amp;.heart.active {
   background-position: -2800px 0;
}
  
 <ion-col *ngFor="let post of postList ; let i = index;">
   <ion-button (click)="toggleFavourite( post, user.userId, '#favourite'   i )">
      <ion-icon [id]="'favourite' i" class="heart" color="pink" [ngClass]="{'active': post.favourites amp;amp; post.favourites[user.userId] ? true : false}"></ion-icon>
   </ion-button>
</ion-col>
  
 import { AnimationController } from '@ionic/angular';

constructor(private animationCtrl: AnimationController){ }

animateForward(elementId){
    const animation = this.animationCtrl
      .create()
      .addElement(document.querySelector(elementId))
      .duration(1000)
      .iterations(1)
      .easing( 'steps(28, end)')
      .keyframes([
        { offset: 0, backgroundPosition: '0 0' },
        { offset: 1, backgroundPosition: '-2800px 0' }
      ])

    animation.play()
  }

  animateBack(elementId){
    const animation = this.animationCtrl
      .create()
      .addElement(document.querySelector(elementId))
      .duration(300)
      .iterations(1)
      .easing( 'steps(28, end)')
      .keyframes([
        { offset: 0, transform: 'scale(0.9)' },
        { offset: 0.7, transform: 'scale(1)' },
        { offset: 1, transform: 'scale(0.9)' }
      ])

    animation.play()
  }