Angular: анимация отображения карты поверх другой карты

#css #angular #angular7 #angular-animations #angular-material-6

#css #angular #angular7 #angular-анимации #angular-материал-6

Вопрос:

Я использую angular animation Builder для создания анимации. У меня есть список сетки со списком карт. Когда я нажимаю на кнопку, я хочу, чтобы другой div был поверх начальной карты (плавающий слева, чтобы закрыть первую карту).На данный момент div поставляется с анимацией, но отображается сбоку от исходной карты.Я создал пример stackblitz, чтобы показать текущий прогресс.Вот мой стекблитц:

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

Также вставляем код сюда:

 import { Component,OnInit,ElementRef } from '@angular/core';
import { trigger, state, style, transition, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations';

export class Asset
{
  constructor(public name:string,public description:string){};
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  assets:Asset[]=[];
  cards=[];
  private player: AnimationPlayer;

  constructor(private animationBuilder:AnimationBuilder,
  private elRef:ElementRef
  ){}

  ngOnInit(){
    this.setAssets();
    this.setswitch();
  }

  setAssets(){
    this.assets.push(new Asset("Asset1","Latest1"));
    this.assets.push(new Asset("Asset2","Latest2"));
    this.assets.push(new Asset("Asset3","Latest3"));
    this.assets.push(new Asset("Asset4","Latest4"));
    this.assets.push(new Asset("Asset5","Latest5"));
    this.assets.push(new Asset("Asset6","Latest6"));
    this.assets.push(new Asset("Asset7","Latest7"));
    this.assets.push(new Asset("Asset8","Latest8"));
    this.assets.push(new Asset("Asset9","Latest9"));

    for(var i=0; i<this.assets.length;i  ){
    console.log(this.assets[i].name);
    }
  }

    setswitch() {
    for (let i = 0; i < this.assets.length; i  ) {
      let cardshow = {
        id: i.toString(),
        isShow : false
      };
      this.cards.push(cardshow);

    }
      console.log(this.cards);
  }

  animate(i){
    this.cards[i].isShow=true;
    let animationFactory;
      animationFactory = this.animationBuilder
        .build([
          style({ width: '0' }),
          animate(200, style({ width: 200 }))
        ]);  
  let elem:Element = document.getElementById("div" (i));
  console.log("Elament",elem);
  console.log("INDEX",i);
  this.player = animationFactory.create(elem);
  this.player.play();

  }
}
  

HTML:

 <div>
    <mat-grid-list cols="3" rowHeight="3:1">
        <mat-grid-tile *ngFor="let asset of assets; index as i">
    <div class="border">
      <p>{{asset.name}} </p>
            <p>{{asset.description}} </p>
            <button (click)="animate(i)">click</button>
         </div>

          <div [ngClass]="!cards[i].isShow?'hide':''" id="{{'div' i}}" class="border" >

            <p>{{asset.description}} </p>
            <button>click</button>
         </div>

  </mat-grid-tile>
</mat-grid-list>
</div>
  

css:

      p {
  font-family: Lato;
}

.border{
  border:1px solid black;
  padding-left: 20px;;
  padding-right:20px;
}

.hide{
  display:none;
}
  

РЕДАКТИРОВАТЬ: мне нужно, чтобы другая карта была полностью скрыта под входящей картой.Также после нажатия на кнопку внутри входящей карты анимация должна быть отменена (карта должна убраться обратно). Также то, что я делаю сейчас, увеличивает ширину. Я ожидаю, что новая карта должна появиться слева, примерно так, как мы видим в ящике

Ответ №1:

проверьте этот stackblitz

app.component.css должен быть:

 p {
  font-family: Lato;
}

.border{
  border:1px solid black;
  padding-left: 20px;;
  padding-right:20px;
  background: #ffe6ea;
}

.hide{
  display:none;
}

.borderPopUp{
  padding-left: 20px;;
  padding-right:20px;
  position:absolute;
  background:#d3d3d3d4;
  animation: openLikeDrawer 800ms ease-in-out;
  width:50%;
  left:20%;
}

@keyframes openLikeDrawer{
  from {left:0px; }
  to { left: 20%; }
}
  

app.component.html быть :

 <div>
    <mat-grid-list cols="3" rowHeight="3:1">
        <mat-grid-tile *ngFor="let asset of assets; index as i">
            <div class="border">
                <p>{{asset.name}} </p>
                <p>{{asset.description}} </p>
                <button (click)="asset.isShow = true">click</button> 

      </div>

      <div *ngIf="asset.isShow" class="borderPopUp" >
        <p>{{asset.description}} </p>
        <button (click)='asset.isShow = false'>click</button>
      </div>

    </mat-grid-tile>
  </mat-grid-list>
</div>
  

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

1. Можете ли вы сделать это немного более похожим на то, что мне нужно. Мне нужно, чтобы другая карта была полностью скрыта под входящей картой. Также после нажатия на кнопку внутри входящей карты анимация должна быть отменена (карта должна убраться обратно).. Также то, что я делаю сейчас, увеличивает ширину. Я ожидаю, что новая карта должна появиться слева, примерно так, как мы видим в ящике

2. позвольте мне поделиться этим мохитом

3. вы хотите использовать angular animate… как насчет того, чтобы сделать это без этого? но чистый angular?

4. не могли бы вы, пожалуйста, проверить мой обновленный stackblitz и сказать мне, что вы думаете об этом. В нем есть еще несколько логических ошибок, которые необходимо исправить

5. замечания (1) слишком много кода для простых вещей… (2) если я открою, а затем закрою ячейку 2 … после этого, если я открою любую ячейку, ячейка 2 снова станет видимой… это то, что портит предполагаемую логику … рассмотрите возможность использования средства визуализации вместо ElementRef для манипулирования DOM (но в конечном итоге избегайте обоих, если можете, с другим дизайном приложения)

Ответ №2:

Это мое окончательное решение:

 import { Component, OnInit } from '@angular/core';
import { LearningContentService } from '../../../service/learningcontent.service';
import { ActivatedRoute } from '@angular/router'

import { trigger, style, transition, animate, keyframes, query, stagger } from '@angular/animations';

export class Asset {
  name: string;
  description: string;
  cardtoggle:boolean=false;
  constructor(rawObj: any) {
    this.name = rawObj.name;
    this.description = rawObj.description;
    this.cardtoggle = rawObj.cardtoggle;

  }
}

@Component({
  selector: 'app-catalogue',
  templateUrl: './catalogue.component.html',
  styleUrls: ['./catalogue.component.scss'],
  animations: [
    trigger('listAnimation', [
      transition('* => *', [

        query(':enter', style({ opacity: 0 }), { optional: true }),

        query(':enter', stagger('50ms', [
          animate('1s ease-in', keyframes([
            style({ opacity: 0, transform: 'translateY(-75%)', offset: 0 }),
            style({ opacity: .5, transform: 'translateY(35px)', offset: 0.3 }),
            style({ opacity: 1, transform: 'translateY(0)', offset: 1.0 }),
          ]))]), { optional: true })
      ])
    ],
    ),
  ]
})
export class CatalogueComponent implements OnInit {
  assets: Array<Asset> = [];

  constructor(private route: ActivatedRoute,
    private learningService: LearningContentService,
  ) {

  }

  ngOnInit() {
    this.loadAssets();

  }


  loadAssets() {
    this.learningService.assets().subscribe((res: any) => {
      const datas: Array<any> = res;
      datas.forEach(asset => this.assets.push(new Asset(asset)));
      console.log(this.assets);
    });
  }

  animate(asset) {
    asset.cardtoggle = true;
  }
  close(asset) {
    asset.cardtoggle = false;
  }
}
  

HTML:

 <div fxLayout="column">
  <div fxLayout="row">
    <p class="page-heading" fxFlex="80%">Catalogue</p>
    <div class="page-content-filter" fxLayoutAlign="end">
      <button mat-button class="search-btn"><i class="material-icons"> search </i></button>
      <input class="form-filter" matInput placeholder="Search...">
    </div>
  </div>
  <mat-grid-list gutterSize="20px" cols="3" rowHeight="3:1" [@listAnimation]="assets.length">
    <mat-grid-tile *ngFor="let asset of assets">
      <div class="full-width white">
        <div class="padding20px" fxLayout="column" fxLayoutGap="15px">
          <div fxLayout="row" fxLayoutGap="15px">
            <img fxFlex="10" style="width:50px;height:50px;" src="../../../../assets/images/images.jpeg" mat-card-image>
            <b fxFlex="100">{{asset.name}}</b>
            <mat-icon fxLayoutAlign="end end" class="small-icon pointer" (click)="animate(asset)">spa</mat-icon>
          </div>
          <div fxLayout="row" fxLayoutGap="10px">
            <mat-icon class="small-icon">person</mat-icon>
            <p class="small-heading"> Mohit Harshan</p>
            <mat-divider vertical="true"></mat-divider>
            <mat-icon class="small-icon">play_arrow</mat-icon>
            <p class="small-heading">Video</p>
            <mat-divider vertical="true"></mat-divider>
            <mat-icon class="small-icon">face</mat-icon>
            <p class="small-heading">5 points</p>
          </div>
          <mat-progress-bar class="progress" mode="determinate" value="40"></mat-progress-bar>
        </div>
      </div>

      <div class="pull-right" [ngClass]="{'show': asset.cardtoggle }" class="card2">
        <div class="padding20px" fxLayout="column" fxLayoutGap="15px">
          <div fxLayout="row" fxLayoutGap="15px">
            <b fxFlex="100" class="small-heading">{{asset.name}}</b>
            <mat-icon fxLayoutAlign="end end" class="small-icon pointer" (click)="close(asset)">clear</mat-icon>
          </div>
          <div fxLayout="row" fxLayoutGap="10px">
           <p class="small">{{asset.description}}</p>
          </div>
          <div fxLayout="row" fxLayoutGap="10px" fxFLex="100" fxLayoutAlign="end end">
            <button fxFLex="100" mat-button class="green-button" >View Details</button>
          </div>
        </div>
      </div>
    </mat-grid-tile>
  </mat-grid-list>
</div>
  

css:

 .card2{ 
    position:absolute; 
    z-index: 20; 
    background: white; 
    padding-left: 0px; 
    padding-right:0px; 
    width:100%; 
    height:100%;
    margin-left: 100%;
    transition: margin-left .5s ease-in-out;
} 

.show { 
    margin-left: 0%;
} 

.green-button{
  border:1px solid lightgreen;
  border-radius: 10%;
  font-size: 10px;
  color:green;
}