重複の可能性:
Android、パスに沿ってビットマップを移動しますか?
曲線パスを介して画像を移動したい.アンドロイドでは可能ですか? 私はたくさん検索しましたが、アニメーションの拡大縮小、回転、翻訳についてしか見つけることができません。
重複の可能性:
Android、パスに沿ってビットマップを移動しますか?
曲線パスを介して画像を移動したい.アンドロイドでは可能ですか? 私はたくさん検索しましたが、アニメーションの拡大縮小、回転、翻訳についてしか見つけることができません。
以下は、3 点で定義された曲線パスに沿ってアニメーション化する、完全に機能するコードです。Point は、x 値と y 値を保持する単なるクラスです (ただし、より多くの次元に簡単に拡張できます)。
すべての m 変数は TranslateAnimation から取得され、同様の方法で使用されるため、何かが意味をなさない場合でも比較的簡単に TranslateAnimation コードと比較できるはずです。
initialize での resolveSize の呼び出しは、通常の TranslateAnimation の場合と同様に、任意のアニメーション タイプ (ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT) を使用して円弧の開始、終了、および半径を指定できることを意味します。
calcBezier はWikipediaから直接取得した 2 次ベジエ曲線を計算します。ベジエ曲線は、滑らかなスケーリングを可能にするはずであり、グラフィックスで一般的です (また、Android の Path クラスでも使用されます)。
実際の移動は applyTransformation で行われます。interpolatedTime は 0 と 1 の間の値を与え、提供される補間器に応じて非線形に増加します。dx と dy は、指定された時間の曲線に沿った実際の x 点と y 点です。
このクラスの唯一の制限は、y の最大の変化が常に曲線の中心で発生することです (初期化の middleX の計算を参照してください)。ただし、たとえば、非対称曲線が必要な場合に、曲線に沿って最高点が発生する特定の点を指定するなど、簡単に変更できます。
TranslateAnimation の Android コードを見ると、特に役に立ちました。参照: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.5_r1/android/view/animation/TranslateAnimation.java#TranslateAnimation
public class ArcTranslate extends Animation {
private Point start;
private Point end;
private Point middle;
private final float mFromXValue;
private final float mToXValue;
private final float mYValue;
private final int mFromXType;
private final int mToXType;
private final int mYType;
/**
* A translation along an arc defined by three points and a Bezier Curve
*
* @param duration - the time in ms it will take for the translation to complete
* @param fromXType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
* @param fromXValue - Change in X coordinate to apply at the start of the animation
* @param toXType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
* @param toXValue - Change in X coordinate to apply at the end of the animation
* @param yType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
* @param yValue - Change in Y coordinate to apply at the middle of the animation (the radius of the arc)
*/
public ArcTranslate(long duration, int fromXType, float fromXValue,
int toXType, float toXValue, int yType, float yValue){
setDuration(duration);
mFromXValue = fromXValue;
mToXValue = toXValue;
mYValue = yValue;
mFromXType = fromXType;
mToXType = toXType;
mYType = yType;
}
/** Calculate the position on a quadratic bezier curve given three points
* and the percentage of time passed.
* from http://en.wikipedia.org/wiki/B%C3%A9zier_curve
* @param interpolatedTime - the fraction of the duration that has passed where 0<=time<=1
* @param p0 - a single dimension of the starting point
* @param p1 - a single dimension of the middle point
* @param p2 - a single dimension of the ending point
*/
private long calcBezier(float interpolatedTime, float p0, float p1, float p2){
return Math.round((Math.pow((1 - interpolatedTime), 2) * p0)
+ (2 * (1 - interpolatedTime) * interpolatedTime * p1)
+ (Math.pow(interpolatedTime, 2) * p2));
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = calcBezier(interpolatedTime, start.x, middle.x, end.x);
float dy = calcBezier(interpolatedTime, start.y, middle.y, end.y);
t.getMatrix().setTranslate(dx, dy);
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
float startX = resolveSize(mFromXType, mFromXValue, width, parentWidth);
float endX = resolveSize(mToXType, mToXValue, width, parentWidth);
float middleY = resolveSize(mYType, mYValue, width, parentWidth);
float middleX = startX + ((endX-startX)/2);
start = new Point(startX, 0);
end = new Point(endX, 0);
middle = new Point(middleX, middleY);
}
}
Monkeyless の回答に触発されました。Animation のサブクラスを作成し、PathMeasure を使用して平行移動を計算します。パスを使用して新しい PathAnimation を作成し、他のアニメーションと同様に使用できます。
https://github.com/coocood/PathAnimation
public class PathAnimation extends Animation {
private PathMeasure measure;
private float[] pos = new float[2];
public PathAnimation(Path path) {
measure = new PathMeasure(path, false);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t){
measure.getPosTan(measure.getLength() * interpolatedTime, pos,null);
t.getMatrix().setTranslate(pos[0], pos[1]);
}
}
フレームごとのアニメーションを実行できます。オブジェクトを段階的に配置して曲線を作成できます。それは限られた再利用になりますが、あなたはそれを行うことができます.
または、独自のアニメーションを作成して、曲線に沿ってアニメーション化できる TweenAnimation のサブクラスを作成することもできます。数学が得意で、ベジエ曲線を理解できる場合、それは簡単なオプションかもしれません。そのクラスを取得すると、曲線のパスを簡単にアニメーション化できますが、それはより多くの作業です。
http://en.wikipedia.org/wiki/B%C3%A9zier_curve
ここにいくつかのJavaコードがあります:
次のように独自のクラスを作成できます。
public class BezierTranslateAnimation extends TranslateAnimation {
private int mFromXType = ABSOLUTE;
private int mToXType = ABSOLUTE;
private int mFromYType = ABSOLUTE;
private int mToYType = ABSOLUTE;
private float mFromXValue = 0.0f;
private float mToXValue = 0.0f;
private float mFromYValue = 0.0f;
private float mToYValue = 0.0f;
private float mFromXDelta;
private float mToXDelta;
private float mFromYDelta;
private float mToYDelta;
private float mBezierXDelta;
private float mBezierYDelta;
public BezierTranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta, float bezierXDelta, float bezierYDelta) {
super(fromXDelta, toXDelta, fromYDelta, toYDelta);
mFromXValue = fromXDelta;
mToXValue = toXDelta;
mFromYValue = fromYDelta;
mToYValue = toYDelta;
mFromXType = ABSOLUTE;
mToXType = ABSOLUTE;
mFromYType = ABSOLUTE;
mToYType = ABSOLUTE;
mBezierXDelta = bezierXDelta;
mBezierYDelta = bezierYDelta;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx=0,dy=0;
if (mFromXValue != mToXValue) {
dx = (float) ((1.0-interpolatedTime)*(1.0-interpolatedTime)*mFromXValue + 2.0*interpolatedTime*(1.0-interpolatedTime)*mBezierXDelta + interpolatedTime*interpolatedTime*mToXValue);
}
if (mFromYValue != mToYValue) {
dy = (float) ((1.0-interpolatedTime)*(1.0-interpolatedTime)*mFromYValue + 2.0*interpolatedTime*(1.0-interpolatedTime)*mBezierYDelta + interpolatedTime*interpolatedTime*mToYValue);
}
t.getMatrix().setTranslate(dx, dy);
}
}
次に、この署名で使用します。
BezierTranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta, float bezierXDelta, float bezierYDelta);