【问题标题】:Android draw animated dotted curveAndroid绘制动画虚线曲线
【发布时间】:2014-04-11 11:42:18
【问题描述】:

这几天我一直没有找到好的解决方案(至少对我来说是这样)。

基本上我需要做的是绘制一个动画虚线,它代表一个基本游戏的导弹轨迹。该轨迹将接受起始、中间和最终 x,y。我刚开始阅读了很多关于动画曲线甚至直线的 Q/A,但与我必须做的相比,它们看起来真的很复杂。

我有一个带有onclick 监听器的按钮,它触发导弹发射,但到目前为止它只是绘制静态线条而没有任何动画。

你还记得吗?这就是我想要实现的目标: http://www.youtube.com/watch?v=UDc3ZEKl-Wc

香蕉轨迹不是画出来的,但是你明白了。


再次在这里,从您的示例开始,我尝试使用数组和 for 循环绘制同时曲线,但我得到的是,有时,并非总是,应用程序因空指针异常而崩溃,不知道为什么。我究竟做错了什么?这是我的代码:

public class DrawDottedCurve extends View {

    Path[] path = new Path[8];
    Path[] drawingPath = new Path[8];
    PathMeasure[] measure = new PathMeasure[8];
    Path[] segmentPath = new Path[8];
    float[] length = new float[8];
    float[] start = new float[8];
    float[] percent = new float[8];
    Paint paint = new Paint();
    float x1;
    float y1;
    float x3;
    float y3;
    long k = 0;
    Canvas canvas;
    Random r = new Random();

    public DrawDottedCurve(Context context, int a, int b, int c, int d) {
        super(context);
        x1 = a;
        y1 = b;
        x3 = c;
        y3 = d;

        paint.setAlpha(255);
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        paint.setStyle(Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50));

        for (int i = 0; i < 8; i++) {
            k = r.nextInt(100 - 30) + 30;
            path[i] = new Path();
            path[i].moveTo(x1 + k, y1 + k); //
            path[i].quadTo((x3 + k - x1 + k) / 2, (y3 + k - y1 + k) / 2,
                    x3 + k, y3 + k); // Calculate Bezier Curves
        }

        final long DRAW_TIME = 10000;
        CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) {

            @Override
            public void onTick(long millisUntilFinished) {
                Log.d("Timer", "Inizio");
                for (int i = 0; i < 8; i++) {
                    start[i] = 0;
                    measure[i] = new PathMeasure();
                    measure[i].setPath(path[i], false);

                    percent[i] = ((float) (DRAW_TIME - millisUntilFinished))
                            / (float) DRAW_TIME;

                    segmentPath[i] = new Path();
                    drawingPath[i] = new Path();
                    length[i] = measure[i].getLength() * percent[i];
                    measure[i].getSegment(start[i], length[i], segmentPath[i],
                            true);
                    start[i] = length[i];
                    drawingPath[i].addPath(segmentPath[i]);


                }
                invalidate();
;
            }

            @Override
            public void onFinish() {
                for (int i = 0; i < 8; i++) {
                    measure[i].getSegment(start[i], measure[i].getLength(),
                            segmentPath[i], true);
                    drawingPath[i].addPath(segmentPath[i]);


                }

                invalidate();   
                Log.d("Timer", "Fine");
            }

        };
        timer.start();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < 8; i++) {
            canvas.drawPath(drawingPath[i], paint);
            invalidate();

        }

    }
}

【问题讨论】:

  • 计算曲线上的点,例如贝塞尔曲线一个接一个地画出来……

标签: android animation bezier


【解决方案1】:

假设您有一个要绘制的 Canvas 和一条您想要跟踪此代码的路径应该可以为它设置动画。

private void init() {
    missilePath = new Path();
    missileDrawPath = new Path();

    mPaint = new Paint();
    mPaint.setStrokeWidth(3);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Style.STROKE);
    mPaint.setAntiAlias(true);

    PathEffect dashEffect = new DashPathEffect(new float[] {2, 4}, 0);
    mPaint.setPathEffect(dashEffect);

    final long DRAW_TIME = 5000;
    timer = new CountDownTimer(DRAW_TIME, 100) {
        PathMeasure measure = new PathMeasure();
        Path segmentPath = new Path();
        float start = 0;

        @Override
        public void onTick(long millisUntilFinished) {
            measure.setPath(missilePath, false);
            float percent = ((float) (DRAW_TIME - millisUntilFinished)) / (float) DRAW_TIME;
            float length = measure.getLength() * percent;
            measure.getSegment(start, length, segmentPath, true);
            start = length;
            missileDrawPath.addPath(segmentPath);
            invalidate();
        }

        @Override
        public void onFinish() {
            measure.getSegment(start, measure.getLength(), segmentPath, true);
            missileDrawPath.addPath(segmentPath);
            invalidate();
        }
    };
    timer.start();
}


@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    c.drawPath(missileDrawPath, mPaint);
}

基本上会启动一个计时器,并根据经过的时间从missilePath 检索一个段并将其添加到当前应绘制的路径中。

【讨论】:

  • 我将在接下来的几天内实现代码并让您知道。谢谢你现在
【解决方案2】:

感谢 SceLus 运行得非常好,这是最终遇到相同问题的人的完整代码。

类构造函数以 Bezier Curve 起始和最终 x's 和 y's 作为输入,简单计算中间控制点,然后根据 SceLus 代码绘制所有内容。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.os.CountDownTimer;
import android.view.View;

public class DrawDottedCurve extends View {

    Path path = new Path();
    Path drawingPath = new Path();
    Paint paint = new Paint();
    float x1;
    float y1;
    float x3;
    float y3;

    public DrawDottedCurve(Context context, int a, int b, int c, int d) {
        super(context);

        x1 = a;
        y1 = b;
        x3 = c;
        y3 = d;

        paint.setAlpha(255);
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        paint.setStyle(Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50));

        path.moveTo(x1, y1); //
        path.quadTo((x3 - x1) / 2, (y3 - y1) / 2, x3, y3); // Calculate Bezier Curve

        final long DRAW_TIME = 10000;
        CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) {
            PathMeasure measure = new PathMeasure();
            Path segmentPath = new Path();
            float start = 0;

            @Override
            public void onTick(long millisUntilFinished) {
                measure.setPath(path, false);
                float percent = ((float) (DRAW_TIME - millisUntilFinished))
                        / (float) DRAW_TIME;
                float length = measure.getLength() * percent;
                measure.getSegment(start, length, segmentPath, true);
                start = length;
                drawingPath.addPath(segmentPath);
                invalidate();
            }

            @Override
            public void onFinish() {
                measure.getSegment(start, measure.getLength(), segmentPath,
                        true);
                drawingPath.addPath(segmentPath);
                invalidate();
            }
        };
        timer.start();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(drawingPath, paint);
    }
}

【讨论】:

    猜你喜欢
    • 2015-02-22
    • 2014-07-24
    • 2011-07-19
    • 2011-02-08
    • 2019-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    相关资源
    最近更新 更多