【问题标题】:How to add CSS AnimationEnd event handler to GWT widget?如何将 CSS AnimationEnd 事件处理程序添加到 GWT 小部件?
【发布时间】:2025-11-27 10:45:02
【问题描述】:

我希望我的 GWT 小部件在其 CSS animation 结束时收到通知。

在普通的 HTML/Javascript 中,这很容易通过注册一个事件处理程序来完成,如下所示:

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

如何在 GWT 中做到这一点?

GWT 的 DOMImpl 类不知道这种类型的事件,所以我不断收到错误消息:

尝试接收未知事件类型 webkitAnimationEnd”。

【问题讨论】:

    标签: dom gwt dom-events css-animations gwt-2.4


    【解决方案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 仍然不知道该事件。脚本动画在重负载或某些移动设备上的性能流畅性方面存在一些缺点。
    • 是的,这将产生脚本动画,它的 CPU 效率可能不如纯 CSS 动画。
    • @Kev 将这两个答案分开会更好......上面的 cmets 指的是该行下方的部分(脚本解决方案)。接受的答案只是该行上方的顶部部分,它描述了一种完全不同的方法。
    【解决方案2】:

    基于 Darthenius 的回答和Clay Lenhart's Blog,我最终确定了这个解决方案:

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

    像魅力一样工作!谢谢达特尼乌斯!

    如果有人能发现这方面的弱点,我当然很乐意知道。

    【讨论】:

    • 不客气。顺便说一句,callback 的抽象很好。
    • 我刚刚修改了上面的代码以排除 MSIE,因为 MSIE 不能做 CSS 关键帧动画(至少到版本 9),并且还需要不同的语法来添加侦听器。
    【解决方案3】:

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

    【讨论】:

      最近更新 更多