实现弯曲动画的问题[重复]
Posted
技术标签:
【中文标题】实现弯曲动画的问题[重复]【英文标题】:Problem to achieve curved animation [duplicate] 【发布时间】:2011-10-14 12:58:53 【问题描述】:可能重复:android, move bitmap along a path?
我想通过弯曲路径移动图像。在 android 中可以吗?我搜索了很多,但我只能找到有关缩放、旋转和翻译动画的信息。所以任何人有任何想法请帮忙。在 android 中可能吗?
【问题讨论】:
看到这个答案:Prepare curve translate animation in Android 【参考方案1】:下面是功能齐全的代码,它将沿着由三个点定义的曲线路径进行动画处理。 Point 只是一个包含 x 值和 y 值的类(尽管您可以轻松地将其扩展为更多维度)。
所有的 m 变量都取自 TranslateAnimation 并以类似的方式使用,因此如果某些东西没有意义,您应该能够相对容易地将其与 TranslateAnimation 代码进行比较。
在 initialize 中调用 resolveSize 意味着您可以使用任何动画类型(ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT)指定弧的起点、终点和半径,就像普通的 TranslateAnimation 一样。
calcBezier 计算直接取自Wikipedia 的二次贝塞尔曲线。 Bezier 曲线应该允许平滑缩放并且在图形中很常见(也用于 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 非常感谢您提供的代码。我设法使用此代码为图像视图设置动画。但是我在动画时将 onClickListener 设置为 imageview 时遇到了麻烦。我已经发布了一个问题here。请帮忙。【参考方案2】:它的灵感来自于 Monkeyless 的回答。 我创建了 Animation 的一个子类,使用 PathMeasure 来计算平移。 您可以使用 Path 创建一个新的 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]);
【讨论】:
我已经使用 Path.addArc() 创建了我希望 View 继续前进的弧线,然后将此解决方案作为动画本身。不错! @vaiden,你能把例子贴在这里吗? 只需创建一个 Path 对象并将其提供给构造函数。没有真正的例子。 我可以像下面这样创建路径来做弯曲的动画吗?我将在哪里提供图像参考。我想在弯曲动画中移动图像 // 初始化路径。路径=新路径(); // 将路径的起始位置设置为 (0,0)。 path.moveTo(0,0); // 在路径中添加一行,从 (0,0) 开始,到 (100, 100) 结束。 path.addArc(0,0,0,0,0,270); 抱歉,我不能使用 addArc()。我的应用最小 API 是 18【参考方案3】:您可以制作逐帧动画。您可以逐步定位对象以创建曲线。这将是有限的重用,但你可以做到。
或者您可以编写自己的动画来创建 TweenAnimation 的子类,该子类可以沿曲线制作动画。如果您擅长数学并且可以理解贝塞尔曲线,那么这可能是一个直接的选择。一旦你有了这个类,你就可以轻松地在任何弯曲的路径上制作动画,但这需要更多的工作。
http://en.wikipedia.org/wiki/B%C3%A9zier_curve
这是一些 Java 代码:
http://www.math.ubc.ca/~cass/gfx/bezier.html
【讨论】:
谢谢。您有任何帖子的示例或链接吗? 你能告诉我如何创建自己的动画类作为补间动画的子类。【参考方案4】:您可以像这样创建自己的类:
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);
【讨论】:
你没有使用动画的类型...以上是关于实现弯曲动画的问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章