3

Can you please guide me on how to create a custom animation in Angular2 equivalent to jQuery .slideUp() and .slideDown(). I know I can use jQuery plugin for this, but many folks recommend not to use it. So I'm looking for an alternate method to create these animations. The slideUp and slideDown will make any div collapsible with smooth animation on click of some button.

Axel
  • 3,331
  • 11
  • 35
  • 58
heman123
  • 3,009
  • 4
  • 24
  • 37

4 Answers4

1

In order to create a custom slideUp/Down for an element we can do the following:

1) Define two states (open, close) with according styles for height. You could also add other styles like opacity or color.

We use the special value * to tell Angular to use the value during execution. This will include margins and paddings.

2) Add a transition to tell Angular how it should go from one state to the other. This will define how intermediate values (tweens) will be calculated. Syntax follows {{total duration}} [{{delay}}] [{{easing function}}]. Time can be expressed in seconds or milliseconds. Eg: .2s, 200ms. Default easing function when omitted is ease.

See below:

@Component({
  selector: 'my-app',
  template: `
    <h1>App</h1>
    <button (click)="toggle()">Toggle</button>
    <div class="card" [@toggle]="state">
      Click to slideUp/Down
    </div>
  `,
  animations: [
    trigger('toggle', [
      state('open', style({ height: '200px' })),
      state('closed', style({ height: '*' })),
      transition('open <=> closed', animate('200ms ease-in-out'))
    ])
  ],
})
export class App {
  state = "open";
  toggle() {
    this.state = (this.state=="open")? "closed": "open";
  }
}

Plunker

Gerard Sans
  • 2,269
  • 1
  • 13
  • 13
1

Below is the animation for slide down and up using dynamic height values.

If there is no margin and/or padding on the object, you can remove those settings.

animations: [
  trigger('slideUpDown', [
    transition('void => *', [
      style({height: 0, margin: 0, padding: 0, opacity: 0}),
      animate(500, style({height: '*', margin: '*', padding: '*', opacity: 1}))
    ]),
    transition('* => void', [
      style({height: '*', margin: '*', padding: '*', opacity: 1}),
      animate(500, style({height: 0, margin: 0, padding: 0, opacity: 0}))
    ])
  ])
] 
Dan Grahn
  • 9,044
  • 4
  • 37
  • 74
Sudhir Mann
  • 61
  • 1
  • 1
  • This is one of the simplest answers for slideup / slidedown. It's important to take into account the margin and padding to avoid jumping at the start or end. This also works nicely with *ngIf, so you don't need to set any state on the animation. – Simon_Weaver Sep 28 '18 at 18:07
  • I would expand that you need to import the trigger, transition from '@angular/animations' to pull this in too. – Mark Jan 29 '20 at 15:52
0

Pure CSS approach:

html

<button (click)="toggleSlide=!toggleSlide">Toggle</button>
<div class="slider closed" [ngClass]="{'closed':!toggleSlide}">
  <div class="content"></div>
</div>

css

.slider {
  max-height: 1000px;
  overflow: hidden;
  transition: max-height 0.5s cubic-bezier(1,0,1,0);
}

.slider.closed {
  max-height: 0;
  transition: max-height 0.7s cubic-bezier(0,1,0,1);
}

.content{
  height: 200px;
  width: 200px;
  background-color: blue;
}

Plunker example here

BogdanC
  • 2,746
  • 2
  • 24
  • 22
-1

You can use Element.animate()

div > div {
  width: 300px;
  height: 200px;
  display: block;
  background: blue;
}
<div>
click
<div></div>
</div>
<script>
  const div = document.querySelector("div");
  const props = ["200px", "0px"]; // from, to
  div.onclick = () => {
    div.firstElementChild.animate({
      height: props
    }, {
      duration: 1000,
      easing: "ease-in-out",
      iterations: 1,
      fill:"forwards"
    })
    .onfinish = function() {
      props.reverse()
    }
  }
</script>
guest271314
  • 1
  • 15
  • 104
  • 177
  • When you click multiple times looks quite odd... Does this provides some sort of `.stop()` ? – Roko C. Buljan Aug 07 '17 at 04:57
  • @RokoC.Buljan No. jQuery is not necessary. The settings can be adjusted. OP did not ask for immediate perfection. The code does not use Angular. The code at Answer uses the `DOM` method [`Element.animate()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) – guest271314 Aug 07 '17 at 04:59
  • Why would he, right ;) Also, what's the browser support for the above? – Roko C. Buljan Aug 07 '17 at 04:59
  • @RokoC.Buljan See link at previous comment. – guest271314 Aug 07 '17 at 05:01
  • @RokoC.Buljan There are various approaches which could be used to prevent `.animate()` being called again when the element is currently being animated. The same issue would occur using jQuery if adjustments were not made to code to prevent the animation being dispatched again while the element is being animated. One approach would be to set the element to `pointer-events:none` or `disabled` at `click` until `.onfinish` is called – guest271314 Aug 07 '17 at 05:04
  • that's a pity party pie (UI breaker) :( – Roko C. Buljan Aug 07 '17 at 05:06
  • @RokoC.Buljan _"that's a pity party pie (UI breaker) :( "_ Not sure what you mean? What is a "UI breaker"? – guest271314 Aug 07 '17 at 05:07
  • 1
    What I mean is 1. you could [edit] to add more details 2. you're suggesting a lousily available feature 3. there's no animation queue buildup clearance 4. prevent pointers seems like a deal breaker. 5. in such case I'd rather suggest a checkbox and CSS3 `max-height` < which looks quite ugly as-well... but at least has a wider support ;) 6. or some almighty-angular alternative – Roko C. Buljan Aug 07 '17 at 05:16
  • @RokoC.Buljan 1. The Question is how to achieve the animation without jQuery, not how to build the perfect animation, 2. the support includes modern borwsers; have not used ie in some time, miss nothing there and would suggest to any user of a browser to use a F(L)OSS browser and thus be rid of ie and edge, 3. not sure what you mean by "animation queue build up clearance"? Again, the post intended to convey the basis of possibilities; there are far more options and capabilities than the code at Answer, 4. "looks ugly" has no relevance to anything other than opinion; yes, CSS is a viable option – guest271314 Aug 07 '17 at 05:17
  • @guest271314 , I can achieve the slide up and down animation using bootstrap collapsible also, thats what i am doing currently. But i am more interested in knowing the angular approach of doing that task. There are many work arounds. Lets get a proper solution in Angular now. – heman123 Aug 07 '17 at 05:20
  • @heman123 Have not used angular and not inclined to. Prefer utilizing the full resources available at the newest releases of modern F(L)OSS browsers. `.animate()` is but one of many options available within the Web Animations API using the `DOM`, without a third party library. Why substitute one third party library for another third party library to achieve same result? If Answer does not meet requirement, that is, as interpreted OP here, to not use jQuery, or requirement includes using a third party library, will delete Answer forthwith. Do advise – guest271314 Aug 07 '17 at 05:23
  • It is pure madness to "downvote" this Answer. Is the Question really about the substitution of one third party library for another third party library? Or make my perfect animation? If it is, then this Answer needs more "downvote" – guest271314 Aug 07 '17 at 05:26
  • 1
    @guest271314 dude relax, I will upvote it to balance. Now just wait for correct Answer. No need to panic. – heman123 Aug 07 '17 at 05:29
  • @heman123 There is no "panic" here. You have JavaScript access to the `Keyframes` themselves using [Web Animations](https://w3c.github.io/web-animations/). What more do you need to achieve virtually any requirement relevant to web animations? What does the "correct answer" consist of? Use of a third party library other than jQuery which accesses the `Keyframes` that Web Animations API does? How would such a rationale be logical? – guest271314 Aug 07 '17 at 05:34
  • @RokoC.Buljan _"Does this provides some sort of `.stop()`"_ Yes, there is a `.pause()` method. Have you read the linked specification? – guest271314 Aug 07 '17 at 05:52