0

I am new with angular and angular animations and I have a problem.

This is my html code:

<div class="main">
  <div class="left" *ngIf="showLeftSide" [@slideInOutLeft]></div>
  <div class="center"></div>
  <div class="right" *ngIf="showRightSide" [@slideInOutRight]></div>
</div>
<div class="footer">
  <button (click)="toggleLeftSide()" class="btn">Toggle Left Side</button>
  <button (click)="toggleRightSide()" class="btn">Toggle Right Side</button>
</div>

What i want to do is when the left or right div is sliding in or out I want that the center div will grow or shrink with animation at the same time that the sliding animation goes on (What I got now is that after the sliding animation finished the center div jumps to fill the free space).

My component code:

@Component({
    selector: 'app-root',
    animations: [
        trigger('slideInOutLeft', [
          transition(':enter', [
            style({transform: 'translateX(-100%)'}),
            animate('500ms', style({transform: 'translateX(0%)'}))
          ]),
          transition(':leave', [
            animate('500ms', style({transform: 'translateX(-100%)'}))
          ])
        ]),
        trigger('slideInOutRight', [
          transition(':enter', [
            style({transform: 'translateX(100%)'}),
            animate('500ms ease-in', style({transform: 'translateX(0%)'}))
          ]),
          transition(':leave', [
            animate('500ms ease-in', style({transform: 'translateX(100%)'}))
          ])
        ])
      ],
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.less']
    })
    export class AppComponent {
      showLeftSide = true;
      showRightSide = true;

      toggleLeftSide() {
        this.showLeftSide = !this.showLeftSide;
      }

      toggleRightSide() {
        this.showRightSide = !this.showRightSide;
      }
    }

My less file:

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
}

.main {
  display: flex;
  height: 95%;

  .left {
    background-color: midnightblue;
    width: 3vw;
    will-change: transform;
  }

  .center {
    background-color: tomato;
    width: 100%;
  }

  .right {
    background-color: aquamarine;
    width: 30vw;
    will-change: transform;
  }
}

.footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: brown;
  width: 100%;
  height: 5%;

  .btn {
    width: 5%;
  }
}

I wish I could upload code snippet but I don't know how to do this for angular 7.

I hope you understand my problem and what I want, sorry for my english and thanks in advance!

Edit:

Live example: https://angular-yej9sz.stackblitz.io/ | https://stackblitz.com/edit/angular-yej9sz

Sagie
  • 996
  • 3
  • 12
  • 25

2 Answers2

1

I have modified some of your code to some extent to achieve the desired output. You can tweak those part.

html

<div class="main">
    <div class="left" [@slideInOutLeft]="showLeftSide">
        Left
    </div>
    <div class="center" [@centerleft]="chnageCenter">Center</div>
    <div class="right"  [@slideInOutRight]="showRightSide">
        Right
    </div>
</div>
<div class="footer">
    <button (click)="toggleLeftSide()" class="btn">Toggle Left Side</button>
  <button (click)="toggleRightSide()" class="btn">Toggle Right Side</button>
</div>

component

 import {
  trigger,
  state,
  animate,
  transition,
  style
} from "@angular/animations";

@Component({
  selector: 'my-app',
  animations: [
    trigger("slideInOutLeft", [
      state("true", style({ width: "340px" })),
      state("false", style({ display: "none" })),
      transition("* => *", animate("300ms linear"))
    ]),
    trigger("slideInOutRight", [
      state("true", style({ width: "340px" })),
      state("false", style({ display: "none" })),
      transition("* => *", animate("300ms linear"))
    ]),
    trigger("centerleft", [
      state("true", style({ width: "calc(100% - 340px )" })),
      state("false", style({ width: "100%" })),
      transition("* => *", animate("300ms  linear"))
    ])
  ],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  showLeftSide = true;
  showRightSide = true;
  chnageCenter = true;

  toggleLeftSide() {
    this.showLeftSide = !this.showLeftSide;
    this.toggleCenter();
  }

  toggleRightSide() {
    this.showRightSide = !this.showRightSide;
    this.toggleCenter();
  }

  toggleCenter() {
    if (this.showRightSide || this.showLeftSide) {
      this.chnageCenter = true;
    }
    else {
      this.chnageCenter = false;
    }
  }
}

here is the output https://angular-cyk5vs.stackblitz.io/
And code: https://stackblitz.com/edit/angular-cyk5vs

Amir
  • 1,855
  • 3
  • 24
  • 40
  • There is no way to do it and keep the `*ngIf`? And do the animation with `transform`? – Sagie Dec 29 '18 at 18:36
  • I don't know why you have to go with *ngIf and transform but shrinking has to do with the width not with the transform. Setting display to none will remove your content from the DOM but animations will jump as @Vega mentioned on another comment. – Amir Dec 29 '18 at 21:21
1

Like in css, Angular animations are not applied to display property. 'Center' div resizing jumps because of display:none. Its animation should be applied to width property (for example) in order to work:

  state("false", style({ width: 0, display:'none' }))

DEMO

Vega
  • 27,856
  • 27
  • 95
  • 103
  • There is no way to do it and keep the `*ngIf`? And do the animation with `transform`? – Sagie Dec 29 '18 at 18:36
  • I just took your demo to reproduce. Could you give me an other demo to see? Why this solution is not good? – Vega Dec 30 '18 at 01:44