9

I'm trying to fade away something from the screen, using:

comp.addStyleName("fade-out");
.fade-out {
    @include valo-animate-out-fade(2500ms, 1000ms);
}

But as soon as the animation ends, it's back on screen as before. Is there any way to get a callback when the animation is done, so I call remove it. Or maybe there is a way to do it in pure SCSS?

I also see that once the animation ran a can't run it again (by removing and adding back style). Is this expected behavior?

EDIT: The second issue was because I remove and add the styles in a listener one after the other. The client will not notice that anything changed, so will not animate. This is corrected by using server pushing, so the removal and new apply is in separate communications.

EDIT 2: Using push I can remove it by spawning a thread, sleeping for the time of the animation and removing. It works, but sounds really ugly. Any better way?

Mordechai
  • 15,437
  • 2
  • 41
  • 82
  • Can you paste the code how you actually use this style? By `addStyleName()` or so? – pirho Dec 26 '17 at 19:07
  • Yes, `addStyleName("fade-out")`. – Mordechai Dec 26 '17 at 19:49
  • Does it have to be exactly "Valo animation" set with style? I've struggled with quite similar problem earlier and ended up with a different solution. – pirho Dec 28 '17 at 19:15
  • @pirho Was it the Animator add-on? I know it works, but once I called an animation, the component couldn't animate anymore with something else. (or maybe I didn't use it correctly? Might be.) In any case, this is built into the theme and should work like expected, no? – Mordechai Dec 28 '17 at 19:32
  • Maybe it should but I could not get it working either with `addStyleName()` without reset & lock. But I have something else that I have working already. Not sure if I can add a callback to it. If iI remeber correct it involved `jQuery` also... – pirho Dec 28 '17 at 19:41
  • What abhout [Animator](https://vaadin.com/directory/component/animator) add-on? – Alex78191 Mar 28 '19 at 16:27
  • @Alex78191 2 comments above. – Mordechai Mar 28 '19 at 17:49

2 Answers2

5

My answer will not deal much about animations in Valo theme but presents a more generic way to deal with JavaScript stuff in Vaadin and includes an option to callback functions in the server side. It requires jQuery but possibly this can be done without it also.

See below example class having callback function on the server side

@SuppressWarnings("serial")
public class AfterFadeCallback implements com.vaadin.ui.JavaScriptFunction {
   @Override
   public void call(JsonArray arguments) {
      Notification.show("Faded!");                  
   }
}

Below is a simple example how to add jQuery library to Vaadin UI and howto call above callback function from client side JavaScript after animation is completed

// jsquery.js is copied to resource directory
// "VAADIN/scripts" (Maven Eclipse project src/main/webapp/VAADIN/scripts )
@com.vaadin.annotations.JavaScript({"vaadin://scripts/jquery.js"})
public class TestUI extends UI {

   @Override
   protected void init(VaadinRequest vaadinRequest) {
      com.vaadin.ui.JavaScript cjs = com.vaadin.ui.JavaScript.getCurrent();
      Button fadeButton = new Button("FADE");
      // need an id for js to find
      fadeButton.setId("fadeButton");
      // add Vaadin JavaScriptFunction to document 
      cjs.addFunction("org.example.javascript.AfterFadeCallback"
                           ,new AfterFadeCallback());
      fadeButton.addClickListener( click -> {
         // complete defines the callback function after animation
         // which is the one we added above
         // of course it can be any js stuff
         cjs.execute("$('#fadeButton').animate({opacity: '0.1'},"
                    +" {duration: 1500, complete: function() { "
                         +" org.example.javascript.AfterFadeCallback() } } );");
      });      
      setContent(fadeButton);
   }

...

}
pirho
  • 11,565
  • 12
  • 43
  • 70
  • Works like a charm! The notification in the callback will not show unless push is used. – Mordechai Jan 01 '18 at 19:41
  • @MouseEvent Nice to know. I think I had no `@Push` added but guess it will not harm if used (need to check & update answer for that part) – pirho Jan 01 '18 at 20:20
4

But as soon as the animation ends, it's back on screen as before

.fade-out {
    @include animation(valo-animate-out-fade 2500ms 500ms forwards);
}

forwards specifies that the target will retain the computed values set by the last keyframe encountered during execution [1]. Note also that I'm not including valo-animate-out-fade directly, because the latter is defined as:

@mixin valo-animate-out-fade ($duration: 180ms, $delay: null){
  @include animation(valo-animate-out-fade $duration $delay backwards);
}

I also see that once the animation ran a can't run it again (by removing and adding back style). Is this expected behavior?

Yes. Remember that Vaadin only communicate changes to the client-side. Since you are removing and adding the style in the same listener call, there are no changes to communicate (i.e. the browser won't be told that the style was removed and added again, then it won't reset the animation).

Is there any way to get a callback when the animation is done, so I call remove it. Or maybe there is a way to do it in pure SCSS?

You cannot remove the component from the DOM by using CSS only (although it will remain hidden if you specify that the animation fills forwards). There is also an approach in [2] by using a Javascript extension, which is similar to the answey by @pirho.

Javier
  • 12,100
  • 5
  • 46
  • 57