17

演習としてGWTのアニメーションクラスで遊んでいます。私の目標は、GWT用にさらに別のウィジェット/アニメーションライブラリを作成することではありません。また、これを行うライブラリがたくさんあることもよく知っています。私がやろうとしているのは、ライブラリの使い方ではなく、これがどのように行われるかを学ぶことです。これは教育目的のみです。

そうは言っても、いくつかのウィジェットで4つの異なるアニメーションを実行する単純なクラスを実装しました:フェードイン、フェードアウト、スライドイン、およびスライドアウト(jQueryのアニメーションモデルに従う)。私がそれをどのように実装したかについては、以下のコードを参照してください。

ライブデモ: http ://www.rodrigo-silveira.com/gwt-custom-animation/

私の質問:別のアニメーションがトリガーされるとすぐにアニメーションをスムーズに[そして正常に]停止し、古いアニメーションを中断したところから現在のアニメーションを続行するにはどうすればよいですか?

たとえば、slideOut()が呼び出されたときにslideIn()が途中である場合、ウィジェットの自然な高さである50%からスライドアウトを開始するにはどうすればよいですか?新しいアニメーションで使用できるように、常に現在の進行状況を追跡するメンバー変数を保持しようとしましたが、正しく取得できないようです。何か案は?

import com.google.gwt.animation.client.Animation;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Element;

public class RokkoAnim extends Animation {

    private Element element;
    private int currentOp;
    private final static int FADE_OUT = 0;
    private final static int FADE_IN = 1;
    private final static int SLIDE_IN = 2;
    private final static int SLIDE_OUT = 3;


    public RokkoAnim(Element element) {
        this.element = element;
    }

    public void fadeOut(int durationMilli) {
        cancel();
        currentOp = RokkoAnim.FADE_OUT;
        run(durationMilli);
    }

    public void fadeIn(int durationMilli) {
        cancel();
        currentOp = RokkoAnim.FADE_IN;
        run(durationMilli);
    }

    public void slideIn(int durationMilli) {
        cancel();
        currentOp = RokkoAnim.SLIDE_IN;
        run(durationMilli);
    }

    public void slideOut(int durationMilli) {
        cancel();
        currentOp = RokkoAnim.SLIDE_OUT;
        run(durationMilli);
    }

    @Override
    protected void onUpdate(double progress) {
        switch (currentOp) {
        case RokkoAnim.FADE_IN:
            doFadeIn(progress);
            break;
        case RokkoAnim.FADE_OUT:
            doFadeOut(progress);
            break;
        case RokkoAnim.SLIDE_IN:
            doSlideIn(progress);
            break;
        case RokkoAnim.SLIDE_OUT:
            doSlideOut(progress);
            break;
        }
    }

    private void doFadeOut(double progress) {
        element.getStyle().setOpacity(1.0d - progress);
    }

    private void doFadeIn(double progress) {
        element.getStyle().setOpacity(progress);
    }

    private void doSlideIn(double progress) {
        double height = element.getScrollHeight();
        element.getStyle().setHeight(height * (1.0d - progress), Unit.PX);
    }

    private void doSlideOut(double progress) {
            // Hard coded value. How can I find out what
            // the element's max natural height is if it's 
            // currently set to height: 0 ?
        element.getStyle().setHeight(200 * progress, Unit.PX);
    }
}

使用法

// 1. Get some widget
FlowPanel div = new FlowPanel();

// 2. Instantiate the animation, passing the widget
RokkoAnim anim = new RokkoAnim(div.getElement());

// 3. Perform the animation

// >> inside mouseover event of some widget:
anim.fadeIn(1500);

// >> inside mouseout event of some widget:
anim.fadeOut(1500);
4

3 に答える 3

8

+=現在の値(または-=割り当てと同等)に基づいて不透明度を更新する必要があります。

private void doFadeOut(double progress) {
    double opacity = element.getStyle().getOpacity();
    element.getStyle().setOpacity(opacity - 1.0d - progress);
}

private void doFadeIn(double progress) {
    double opacity = element.getStyle().getOpacity();
    element.getStyle().setOpacity(opacity + progress);
}
于 2013-01-19T17:36:03.093 に答える
1
  1. キャンセルされたインスタンスメソッドboolをアニメーションクラスに追加します
  2. キャンセルされない場合にのみ、アニメーションを実行します。
  3. メソッドcancelAnnimationを追加し、新しいアニメーションが開始するたびにこのメソッドを呼び出します。

    private bool canceled = false;
    
    public void cancelAnnimation() {
        canceled = true;
    }
    
    private void doFadeOut(double progress) {
        if(!canceled) {
           element.getStyle().setOpacity(1.0d - progress);
        }
    }
    
    ... etc.
    

これで、アニメーションを停止できます。ただし、ここで、現在のポイントから新しいアニメーションを開始する必要があります。したがって、クラスを再度変更するのが最善でした。

  1. 2つのインスタンス変数currentProgressとoffset(double)を追加します
  2. コンストラクターにダブルオフセットを追加します
  3. アニメーションをキャンセルすると、currentProgressを返します。
  4. 最初のアニメーションからのオフセットで新しいアニメーションを開始します。

    private bool canceled = false;
    private double currentProgress = 0;
    private double offset = 0;
    
    public RokkoAnim(Element element, double offset) {
        this.element = element;
        this.offset = offset;
    }
    
    public double cancelAnimation() {
        canceled = true;
        return currentProgress;
    }
    
    private void doFadeOut(double progress) {
    
        if(!canceled && ((progress + offset) <= 1)) {
           element.getStyle().setOpacity(1.0d - (progress+offset));
           currentProgress = progress+offset;
        }
    }
    
    ... etc.
    
    
    double offset = anim1.cancelAnimation();
    RokkoAnim anim2 = new RokkoAnim(div.getElement(), offset);
    
于 2013-01-18T16:08:40.300 に答える
0

スライドインおよびスライドアウトの場合、ウィジェット画面の座標を使用するためにクラスを変更しました。

public class WidgetAnimation extends Animation {

    private Element element;
    private int currentOp;
    private int startX=-1;
    private int finalX=-1;
    private final static int FADE_OUT = 0;
    private final static int FADE_IN = 1;
    private final static int SLIDE_IN = 2;
    private final static int SLIDE_OUT = 3;


    public WidgetAnimation(Element element) {
        this.element = element;
    }

    public void fadeOut(int durationMilli) {
        cancel();
        currentOp = WidgetAnimation.FADE_OUT;
        run(durationMilli);
    }

    public void fadeIn(int durationMilli) {
        cancel();
        currentOp = WidgetAnimation.FADE_IN;
        run(durationMilli);
    }

    public void slideIn(int durationMilli) {
        cancel();
        currentOp = WidgetAnimation.SLIDE_IN;
        run(durationMilli);
    }

    public void slideOut(int durationMilli) {
        cancel();
        currentOp = WidgetAnimation.SLIDE_OUT;
        run(durationMilli);
    }

    @Override
    protected void onUpdate(double progress) {
        switch (currentOp) {
        case WidgetAnimation.FADE_IN:
            doFadeIn(progress);
            break;
        case WidgetAnimation.FADE_OUT:
            doFadeOut(progress);
            break;
        case WidgetAnimation.SLIDE_IN:
            doSlideIn(progress);
            break;
        case WidgetAnimation.SLIDE_OUT:
            doSlideOut(progress);
            break;
        }
    }

    private void doFadeOut(double progress) {
        element.getStyle().setOpacity(1.0d - progress);
    }

    private void doFadeIn(double progress) {
        element.getStyle().setOpacity(progress);
    }

    private void doSlideIn(double progress) {
        if(startX==-1){
            finalX = element.getAbsoluteLeft();
            startX = - Window.getClientWidth();
        }

        int positionX = (int) (startX + (progress * (this.finalX - startX)));

        this.element.getStyle().setLeft(positionX, Unit.PX);
    }

    private void doSlideOut(double progress) {
        if(startX==-1){
            startX = element.getAbsoluteLeft();
            finalX = - Window.getClientWidth();
        }

        int positionX = (int) (startX + (progress * (this.finalX - startX)));
        GWT.log("StartX:" + startX);
        GWT.log("finalX:" + finalX);
        GWT.log("positionX:" + positionX);
        GWT.log("progress:" + progress);

        this.element.getStyle().setLeft(positionX, Unit.PX);
    }

}

スライドして水平に移動していますが、コードを変更できます。

それがお役に立てば幸いです。

于 2017-04-13T07:04:11.150 に答える