概要

画像の上にJTextAreaをスライドインアニメーションで表示します。

サンプルコード

private int delay = 4;
private int count = 0;
@Override public void mouseEntered(MouseEvent e) {
  if (animator != null && animator.isRunning() ||
     yy == textArea.getPreferredSize().height) return;
  final double h = (double) textArea.getPreferredSize().height;
  animator = new Timer(delay, new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      double a = easeInOut(++count / h);
      yy = (int) (.5 + a * h);
      textArea.setBackground(new Color(0f, 0f, 0f, (float) (.6 * a)));
      if (yy >= textArea.getPreferredSize().height) {
        yy = textArea.getPreferredSize().height;
        animator.stop();
      }
      revalidate();
      repaint();
    }
  });
  animator.start();
}
@Override public void mouseExited(MouseEvent e) {
  if (animator != null && animator.isRunning() ||
     contains(e.getPoint()) && yy == textArea.getPreferredSize().height) return;
  final double h = (double) textArea.getPreferredSize().height;
  animator = new Timer(delay, new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
      double a = easeInOut(--count / h);
      yy = (int) (.5 + a * h);
      textArea.setBackground(new Color(0f, 0f, 0f, (float) (.6 * a)));
      if (yy <= 0) {
        yy = 0;
        animator.stop();
      }
      revalidate();
      repaint();
    }
  });
  animator.start();
}
//@see Math: EaseIn EaseOut, EaseInOut and Beziér Curves | Anima Entertainment GmbH
//http://www.anima-entertainment.de/math-easein-easeout-easeinout-and-bezier-curves
public double easeInOut(double t) {
  //range: 0.0 <= t <= 1.0
  if (t < .5) {
    return .5 * Math.pow(t * 2d, 3d);
  } else {
    return .5 * (Math.pow(t * 2d - 2d, 3d) + 2d);
  }
}
view all

解説

上記のサンプルでは、JLabelに画像を表示し、これにマウスカーソルが入った場合、JTextAreaがキャプションとしてease-in, ease-outでスライドインするようになっています。

  • OverlayLayout#layoutContainer内で、JTextAreay座標を変更してアニメーション
  • EaseInOutの計算は、Math: EaseIn EaseOut, EaseInOut and Beziér Curves | Anima Entertainment GmbHを参考
  • マウスカーソルがJLabel(画像)内にあっても、そこにJTextAreaがスライドインした場合、mouseExitedが発生するので、注意
    • JTextArea#contains(int x, int y)が常にfalseを返すようにすれば、上記の場合でもmouseExitedなどは発生しないが、JTextArea内の文字列が選択できなくなるので、このサンプルでは、JTextAreaにマウスイベントを親へ素通しするリスナーを追加している
  • JTextAreaの背景色はsetOpaque(false)にして描画せず、別途JTextArea#paintComponent(...)をオーバーライドしてアルファ成分をEaseInOutした色で全体を塗りつぶしている

メモ: 累乗をMath.pow(...)の代わりにバイナリ法で

public static double intpow(double x, int n) {
  double aux = 1d;
  if (n < 0) {
    throw new IllegalArgumentException("n must be a positive integer");
  }
  for (; n > 0; x *= x, n >>>= 1) {
    if ((n & 1) != 0) {
      aux *= x;
    }
  }
  return aux;
}

参考リンク

コメント