安卓绘制动态虚线曲线

3

我已经进行了几天的尝试,但没能找到一个好的解决方案(至少对我来说是这样)。

基本上我需要做的是绘制一条动态虚线曲线,用于表示基础游戏的导弹轨迹。这条轨迹将接受起始、中间和最终的x、y坐标。我读了很多有关动画曲线甚至直线绘制的问答,但与我要做的相比,它们看起来非常复杂。

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

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

香蕉轨迹没有被绘制出来,但你已经有了这个想法。


在您的示例的基础上,我尝试使用数组和for循环同时绘制曲线,但有时候,不总是,应用程序会因为nullpointer异常而崩溃,我不知道原因。我在这里发布了我的代码:

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

        }

    }
}

计算曲线上的点,比如贝塞尔曲线,并依次绘制它们... - ElDuderino
2个回答

1
假设您有画布可供绘制,并且需要跟踪的路径,此代码应该可以实现动画效果。
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中检索一个片段,并将其添加到当前应该绘制的路径中。

我会在接下来的几天内实现这段代码并告知您。谢谢。 - user3523425

0

感谢SceLus,这个方法非常有效。以下是完整的代码,供那些遇到同样问题的人参考。

类构造函数以贝塞尔曲线起始和终止x和y作为输入,并简单地计算中间控制点,然后根据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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接