如何为GWT小部件添加CSS AnimationEnd事件处理程序?

5

我希望我的GWT小部件在其CSS动画结束时得到通知。

在普通的HTML / Javascript中,可以通过注册事件处理程序轻松完成此操作,如下所示:

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

我该如何在GWT中实现这个功能?
这种类型的事件对于GWT的DOMImpl类来说是未知的,因此我一直收到错误信息:
“尝试下沉未知事件类型webkitAnimationEnd”。
3个回答

5

根据Darthenius的回答和Clay Lenhart的博客,我最终选择了这个解决方案:

private native void registerAnimationEndHandler(final Element pElement,
    final CbAnimationEndHandlerIF pHandler)
/*-{
    var callback = function(){
       pHandler.@fully.qualified.CbAnimationEndHandlerIF::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();
}

太棒了!谢谢Darthenius!

如果有人发现其中的漏洞,当然我很乐意知道。


不客气。顺便说一下,callback 的抽象化很好。 - Rok Strniša
我刚刚修改了上面的代码,排除了MSIE,因为MSIE不能执行CSS关键帧动画(至少到版本9),并且需要不同的语法来添加监听器。 - barfuin

1

你总是可以自己编写一些本地(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的Animation类来实现相同的效果。例如,

  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);

有趣,我不知道这个。但是用这种方式做会导致脚本动画,而不是CSS动画,对吧?GWT仍然不知道这个事件。在重负载或某些移动设备上,脚本动画在性能平滑度方面存在一些缺点。 - barfuin
是的,这将导致脚本动画,可能不如纯CSS动画CPU效率高。 - Rok Strniša
1
@Kev 最好将这两个答案分开...上面的评论是指下面那部分(脚本解决方案)。被接受的答案只是上面那部分,描述了完全不同的方法。 - barfuin

0

我对Darthenius的解决方案进行了一些扩展。这段代码还包括一个在处理完毕后移除事件处理程序的机制。这是我在应用程序中所需要的,但并不是您在所有情况下都想要的。 YMMV!

我的最终代码如下:

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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接