2011-07-27 8 views
5

Powiel możliwe:
Android, move bitmap along a path?Problem osiągnąć zakrzywioną animacja

Chcę przenieść obraz za pomocą zakrzywionych path.Is to możliwe w android? Dużo szukałem, ale mogę tylko znaleźć skalę, obrócić i przetłumaczyć animację. Każdy ma jakiś pomysł, proszę o pomoc. Czy to możliwe w Androidzie?

+0

Zobacz tę odpowiedź: [Przygotowanie krzywej tłumaczyć animację w Android] (http://stackoverflow.com/questions/8354441/how-to-prepare-curve-translate-animation-for- android/27948353 # 27948353) – Sheharyar

Odpowiedz

1

Możesz zrobić animację klatka po klatce. Możesz ustawić obiekt krok po kroku, aby utworzyć krzywą. To będzie ograniczone ponowne użycie, ale możesz to zrobić.

Można też napisać własną animację, aby utworzyć podklasę animacji TweenAnimation, która może animować wzdłuż krzywej. Jeśli jesteś dobry z matematyką i potrafisz zrozumieć krzywe Beziera, to może to być prosta opcja. Gdy już będziesz mieć tę klasę, możesz łatwo animować na dowolnej zakrzywionej ścieżce, ale to więcej pracy.

http://en.wikipedia.org/wiki/B%C3%A9zier_curve

Oto niektóre kodu Java:

http://www.math.ubc.ca/~cass/gfx/bezier.html

+0

Dzięki. Masz jakiś przykład lub dowolny link do dowolnego postu? –

+0

Czy możesz mi powiedzieć, jak mogę utworzyć własną klasę animacji jako podklasę animacji? –

9

Poniżej pełni funkcjonujący kod, który będzie animować wzdłuż zakrzywionej ścieżki wyznaczonej przez trzy punkty. Punkt jest po prostu klasą trzymającą wartość xi wartość y (choć można ją łatwo rozszerzyć dla większej ilości wymiarów).

Wszystkie zmienne m są pobierane z TranslateAnimation i używane w podobny sposób, więc powinieneś być w stanie porównać to z kodem TranslateAnimation względnie eaSILY, jeśli coś nie ma sensu.

Wywołania funkcji resolveSize in initialize oznaczają, że możesz określić początek, koniec i promień łuku za pomocą dowolnego z typów animacji (ABSOLUTE, RELATIVE_TO_SELF, RELATIVE_TO_PARENT), tak jak w przypadku zwykłej funkcji TranslateAnimation.

calcBezier oblicza kwadratową krzywą Beziera pobraną bezpośrednio z Wikipedia. Krzywa Beziera ma umożliwiać płynne skalowanie i jest powszechna w grafice (a także używana w klasie Path systemu Android).

Rzeczywisty ruch odbywa się w applyTransformation. interpolatedTime daje wartość między 0 a 1, która wzrasta nieliniowo w zależności od dostarczonego interpolatora. dx i dy są rzeczywistymi punktami x i y wzdłuż krzywej dla danego czasu.

Jedynym ograniczeniem tej klasy jest to, że największa zmiana y zawsze występuje w środku krzywej (zobacz obliczenia dla średniego X w inicjalizacji). Można jednak łatwo zmodyfikować, na przykład, nadać określony punkt na krzywej, w której powinien wystąpić punkt wysoki, jeśli chcemy uzyskać niesymetryczną krzywą.

Patrząc na kod androida dla TranslateAnimation był szczególnie pomocny.Zobacz: 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); 
} 
} 
+0

@Monkeyless Dziękuję bardzo za kod. Udało mi się animować widok obrazu za pomocą tego kodu. Ale mam problem z ustawieniem onClickListener do wyświetlenia obrazu podczas animowania. Zadałem pytanie [tutaj] (http://stackoverflow.com/questions/23947114/onclicklistener-not-triggered-during-animation). Proszę pomóż. –

0

Można tworzyć własne klasy tak:

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

    } 

} 

następnie używać go z tego podpisu:

BezierTranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta, float bezierXDelta, float bezierYDelta); 
+0

nie używasz typów animacji ... –

5

Został on zainspirowany odpowiedź Monkeyless użytkownika. Utworzono podklasę animacji, użyj narzędzia PathMeasure, aby obliczyć tłumaczenie. Możesz po prostu utworzyć nową ścieżkę animacji za pomocą ścieżki i używać jej tak, jak innych animacji.

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]); 
} 
} 
+0

Użyłem Path.addArc() do utworzenia łuku, który chcę, aby mój widok podróżował, a następnie to rozwiązanie jako animacji. Miły! – Vaiden

+0

@vaiden, czy możesz umieścić tutaj przykład? – Geetha

+1

Po prostu utwórz obiekt Path i podaj go do konstruktora. Tak naprawdę nie ma takiego przykładu. – Vaiden