Как добавить обработчик событий CSS AnimationEnd в виджет GWT?

Я хочу, чтобы мой виджет GWT уведомлялся об окончании его CSS-анимации.

В простом HTML/Javascript это легко сделать, зарегистрировав обработчик событий следующим образом:

elem.addEventListener("webkitAnimationEnd", function(){
    // do something
}, false);
// add more for Mozilla etc.

Как я могу сделать это в GWT?

Этот тип события неизвестен классам DOMImpl GWT, поэтому я продолжаю получать сообщение об ошибке:

Попытка передать неизвестный тип события webkitAnimationEnd.


person barfuin    schedule 23.11.2011    source источник


Ответы (3)


Вы всегда можете написать часть нативного (JavaScript) кода самостоятельно:

public class CssAnimation {
  public static native void registerCssCallback(
      Element elem, AsyncCallback<Void> callback) /*-{
    elem.addEventListener("webkitAnimationEnd", function() {
      $entry(@CssAnimation::cssCallback(Lcom/google/gwt/user/client/rpc/AsyncCallback;)(callback));
    }, false);
  }-*/;


  protected static void cssCallback(AsyncCallback<Void> callback) {
    callback.onSuccess(null);
  }
}

Я не пробовал код выше. Дайте мне знать, если это работает, как ожидалось.


Вы можете использовать анимацию GWT. для достижения того же эффекта. Например,

  new com.google.gwt.animation.client.Animation() {
    final com.google.gwt.dom.client.Style es = widget.getElement().getStyle();

    @Override
    protected void onUpdate(double progress) {
      setOpacity(1 - interpolate(progress));
    }

    private void setOpacity(double opacity) {
      es.setProperty("opacity", Double.toString(opacity));
      es.setProperty("filter", "alpha(opacity=" + 100 * opacity + ")");
    }

    @Override
    protected void onComplete() {
      /* ... run some code when animation completes ... */
    }
  }.run(2000, 5000);
person Rok Strniša    schedule 24.11.2011
comment
Интересно, я этого не знал. Но если сделать это таким образом, получится скриптовая анимация, а не CSS-анимация, верно? GWT до сих пор не знает об этом событии. Скриптовые анимации имеют некоторые недостатки, когда речь идет о плавности работы при большой нагрузке или на некоторых мобильных устройствах. - person barfuin; 24.11.2011
comment
Да, это приведет к анимации по сценарию, которая может не так эффективно использовать ЦП, как чистая анимация CSS. - person Rok Strniša; 24.11.2011
comment
@Kev Было бы лучше разделить эти два ответа ... Комментарии выше относятся к разделу под строкой (решение по сценарию). Принятый ответ - это только верхняя часть над линией, которая описывает совершенно другой подход. - person barfuin; 01.05.2012

На основе ответа Дартениуса и блога Клея Ленхарта, я наконец остановился на этом решении:

private native void registerAnimationEndHandler(final Element pElement,
    final CbAnimationEndHandlerIF pHandler)
/*-{
    var callback = function(){
       [email protected]::onAnimationEnd()();
    }
    if (navigator.userAgent.indexOf('MSIE') < 0) {  // no MSIE support
       pElement.addEventListener("webkitAnimationEnd", callback, false); // Webkit
       pElement.addEventListener("animationend", callback, false); // Mozilla
    }
}-*/;

CbAnimationEndHandlerIF — это простой пользовательский интерфейс EventHandler:

public interface CbAnimationEndHandlerIF extends EventHandler
{
    void onAnimationEnd();
}

Работает как шарм! Спасибо, Дартениус!

Если кто-то может найти слабость в этом, конечно, я был бы рад узнать.

person barfuin    schedule 24.11.2011
comment
Пожалуйста. Между прочим, хорошая абстракция для callback. - person Rok Strniša; 26.11.2011
comment
Я только что изменил свой код выше, чтобы исключить MSIE, потому что MSIE не может выполнять анимацию ключевых кадров CSS (по крайней мере, до версии 9), а также требует другого синтаксиса для добавления прослушивателя. - person barfuin; 06.12.2011

Я немного расширил решение Дартениуса. Этот код также включает механизм удаления обработчика событий после его завершения. Это то, что мне нужно для моего приложения, но может быть не то, что вам нужно во всех контекстах. ИММВ!

Мой окончательный код выглядит так:

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class CssAnimation {
    public static native void registerCssCallback(Element elem, AsyncCallback<Void> callback) /*-{
        var eventListener = function () {
            $entry(@CssAnimation::cssCallback(Lcom/google/gwt/user/client/rpc/AsyncCallback;)(callback));
            elem.removeEventListener("webkitAnimationEnd", eventListener);
        };

        elem.addEventListener("webkitAnimationEnd", eventListener, false);
    }-*/;

    protected static void cssCallback(AsyncCallback<Void> callback) {
        callback.onSuccess(null);
    }
}
person Tim Mattison    schedule 25.02.2015