モジュール 4 タスク 1: フリックスクロールの実装


JavaFX メディアブラウザアプリケーションを起動する NetBeans プロジェクトをダウンロードする

はじめに

「モジュール 4 タスク 1」では、マウスイベントの機能と物理エンジンによるアニメーションについて検証し、「モジュール 2 タスク 2」の ScrollControl.fx ノードで紹介したスクロールコントロール機能にフリックスクロールを追加します。今回のタスクの手順を終える前に、「モジュール 2 タスク 2」のスクロールコントロール機能を再確認してください。

フリックスクロールは、マウスを放したときにマウスドラッグをスクロールアニメーションに変換することで実現されます。アニメーションでスクロールコントロールのエレベータの位置を更新し、それに合わせてサムネイル画像の壁を動かします。画像の壁がサムネイル配列の終端を超えてスクロールする場合は、バウンドアニメーション効果が働きます。

プロジェクトの実行

  1. モジュール 4 タスク 1 NetBeans プロジェクトをダウンロードして、NetBeans IDE を開きます。

  2. プロジェクトを実行します。

検索テキストボックスが付いた壁 図 1

アーキテクチャー

このタスクでは、ScrollControl.fx にフリックスクロール機能を追加します。

モジュール 4 タスク 1 のアーキテクチャー 図 2

マウスイベントの処理

フリックスクロールは、ドラッグジェスチャー、つまりマウスの左ボタンをクリックし、そのままドラッグして、ボタンを放すことにより開始されます。マウスボタンを放したときに、ジェスチャーが十分な速度であれば、フリックアニメーションが開始されます。そうでない場合は、ドラッグジェスチャーにより壁のサムネイルが単にスクロールされるだけです。

ローカル変数 lastDragTimelastDragX、および dragSpeed は、ドラッグジェスチャーでのマウスの動きを監視するために使用されます。これに関係する関数は、onMousePressedonMouseDraggedonMouseReleased の 3 つです。これらの変数は、onMousePressed で初期化されます。ユーザーがマウスをドラッグするのに合わせて、onMouseDragged で更新されます。最後に、onMouseReleased で評価され、アニメーションを表示するかどうかが決定されます。

次のソースコードサンプルに示す onMouseDragged 関数は、ユーザーがマウスをドラッグすると呼び出されます。MouseEvent 関数の dragX の値は、前の値からの差分です。マウスの動きが小さいと、壁はスクロールしません。したがって、MouseEventdragX の値が、一定のしきい値を超えることが必要になります。

dragSpeed は単に、マウスの移動距離を移動時間で除算して計算されます (注 距離 = 速度 * 時間)。

ソースコード
    onMouseDragged: function(evt: MouseEvent): Void {
        var dragTime = Duration.valueOf(java.lang.System.currentTimeMillis());
        if (java.lang.Math.abs(evt.dragX) > Constants.FLICK_DRAG_THRESHOLD) {
                            
            // Set the elevator's dragging flag to prevent its
            // overlay from recentering on every mouse event.
                 
            dragging = true;
            position = posAnchor - evt.dragX / (contentWidth - windowWidth);

            // Monitor the dragging speed.
			
            dragSpeed = (evt.dragX - lastDragX) / 
			dragTime.sub(lastDragTime).toMillis();
            
            if (dragSpeed > Constants.FLICK_MAX_SPEED) {
               dragSpeed = Constants.FLICK_MAX_SPEED;
               } else if (dragSpeed < -Constants.FLICK_MAX_SPEED) {
                 dragSpeed = -Constants.FLICK_MAX_SPEED;
               }
               lastDragTime = dragTime;
               lastDragX = evt.dragX;
            }
      }

onMouseReleased 関数は、それより複雑です。マウスボタンを放したとき、onMouseReleased は次の条件に基づいて、フリックアニメーションを表示するかどうかを決定します。

  • ユーザーが Constants.FLICK_DRAG_THRESHOLD の値よりも大きくマウスをドラッグしたか。FLICK_DRAG_THRESHOLD は、スクロールを発生させるための、ピクセル単位で表したマウスの最小ドラッグ距離です。

  • ユーザーが通常のスクロール制限を越えて壁をドラッグしたか。

  • Constants.FLICK_TIME_THRESHOLD 値よりも長く壁の動作が持続するマウスのドラッグ速度か。FLICK_TIME_THRESHOLD は、アニメーションを表示するための最小時間です。

これらの条件に適合した場合、壁が新しい位置にスクロールするアニメーションのための Timeline が新しい位置に作成されます。Timeline によって、flickOffset の値が補間されます。flickOffset の値が変更されると、position 変数が更新されます。positionWall.scrollPosition の逆の値にバインドされているため、position が更新されると、壁はスクロールします。「モジュール 2 タスク 2」の「算術計算」を参照してください。

ソースコード
  flickTimeline = Timeline {
      keyFrames: [
         at (0s) {
           flickOffset => scrollOffset tween flickInterpolator
          },
          KeyFrame {
            time: Duration.valueOf(restTime)
            action: bounce
            values: [
            flickOffset => restOffset tween flickInterpolator
            ]                        
          }
       ];
    };

補間は javafx.animation.Interpolator では行われず、カスタムの FlickInterpolator に、アニメーション用のモーションの等加速度式が指定されています。FlickInterpolator は、javafx.animation.Interpolator を拡張して interpolate 関数をオーバーライドしたものです。interpolate 関数は、KeyFrame の継続時間中に繰り返し呼び出され、指定された KeyFrame の開始値と終了値の間で値のシーケンスを効果的に作成します。

fraction 引数は、KeyFrame 継続時間を小数で表したものです。たとえば、fraction の値が .5 の場合、KeyFrame の継続時間の半分が経過したことを表します。startValue は、KeyFrame の開始時点の値です。interpolate 関数のコントラクトは、startValueendValue の間の値を返す関数になります。

interpolate 関数は等加速度式を使用して、スクロール制限に達して停止するための、壁の初期速度を決定します。

x = x0 + v0 * t + a * t^2 / 2

したがって、v0 = (x0 - x + a * t^2 / 2) / t となります。ここで、x0 は終了後の初期位置、x はスクロール制限の位置、a は等加速度、t はバウンドさせるための一定の時間を表します。

ソースコード
class FlickInterpolator extends Interpolator {

    // Initial position
    var x0: Number;
			
    // Initial velocity
    var v0: Number;
			
    // The time at which the object comes to rest.
    var t1: Number;
			
    override function interpolate(startValue: java.lang.Object,
             endValue: java.lang.Object,fraction: Number) :   
             java.lang.Object {
			
             // The sign of the acceleration parameter is based on the
			 // direction of motion.
   
             var a : Number = bind if (v0 > 0) {
			 Constants.FLICK_ACCELERATION;
             } else {
             -Constants.FLICK_ACCELERATION;
             }
			   
             // The interpolation always begins at t = 0 so
             // t = t0 + (t1 - t0) * fraction becomes
             // t = t1 * fraction
			        
             var t = fraction * t1;
			
             // Apply the motion formula for constant acceleration.
						   
             return x0 + v0 * t + a * t * t / 2;
    }
}                

バウンドアニメーション

フリックアニメーションが動いた場合、またはユーザーがサムネイルの列を越えて壁をドラッグした場合、バウンドアニメーションが表示されます。バウンドアニメーションは、FlickInterpolator を使用して、スクロール制限に一定の時間で壁を戻すことを簡単に表現したものです。

ソースコード
    var restOffset = 0.0;
    var a = -Constants.FLICK_ACCELERATION;
    if (scrollOffset <= 0) {
       restOffset = -(contentWidth - windowWidth);
       a *= -1;
    }

    // Compute the initial rebound velocity based on the position and
    // the defined bounce duration.
       
       var v0 = (restOffset - scrollOffset -
       a * Constants.FLICK_BOUNCE_TIME * Constants.FLICK_BOUNCE_TIME / 2) /
       Constants.FLICK_BOUNCE_TIME;

     // Create a motion formula interpolator for the bounce animation.
	 
     var flickInterpolator = FlickInterpolator {
         x0: scrollOffset
         v0: v0
         t1: Constants.FLICK_BOUNCE_TIME;
     }

フリックアニメーションの調整

次の表に示されているのは、Constants.fx に追加され、フリックアニメーションの動作の調整に使用できる変数です。

フリックアニメーションの調整に使用される変数
定数 意味
FLICK_DRAG_THRESHOLD スクロールのトリガーを発生するために必要な、マウスドラッグの最小距離 (ピクセル単位)。 5 ピクセル
FLICK_TIME_THRESHOLD フリックアニメーションの最小継続時間。これより短いと、アニメーションが短すぎて表示効果が得られません。 500 ミリ秒
FLICK_ACCELERATION フリック後のスクロールの加速 (ピクセル / ms / ms 単位)。フリックの物理計算で、この値は (マイナスの値で) 摩擦抵抗を表します。 - 0.00035 ピクセル / ms / ms
FLICK_MAX_SPEED 壁が (3500) ミリ秒以内でスクロールを停止するための、初期速度の最大制限値。 - FLICK_ACCELERATION * 3500
FLICK_BOUNCE_LIMIT フリックアニメーションが行き過ぎることのできる距離 (ピクセル単位)。 100 ピクセル
FLICK_BOUNCE_TIME 壁が行き過ぎたときにバウンド (逆方向にスクロール) する秒数 (ミリ秒単位)。 750 ミリ秒

 

English
日本語
한국어
简体中文
Português do Brasil
русский