Cómo animar un camino en canvas-android


¿Es posible adjuntar un animador a una ruta? ¿Hay alguna otra forma de dibujar en lienzo líneas animadas? Busqué esto antes de publicar, pero no hay nada sobre esto. En otros dos mensajes aquí y aquí hay soluciones de paseo y no se ajustan a mí. ¡Gracias!

Publico mi código dentro del método onDraw para especificar exactamente lo que quiero.

paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(2);
    paint.setColor(Color.BLACK);

    Path path = new Path();
    path.moveTo(10, 50);   // THIS TRANSFORMATIONS TO BE ANIMATED!!!!!!!!
    path.lineTo(40, 50);
    path.moveTo(40, 50);
    path.lineTo(50, 40);
    // and so on...


    canvas.drawPath(path, paint);

¿Alguna idea????

Author: Community, 2013-09-04

3 answers

Puedes transformar tu lienzo por tiempo, es decir:

class MyView extends View {

    int framesPerSecond = 60;
    long animationDuration = 10000; // 10 seconds

    Matrix matrix = new Matrix(); // transformation matrix

    Path path = new Path();       // your path
    Paint paint = new Paint();    // your paint

    long startTime;

    public MyView(Context context) {
        super(context);

        // start the animation:
        this.startTime = System.currentTimeMillis();
        this.postInvalidate(); 
    }

    @Override
    protected void onDraw(Canvas canvas) {

        long elapsedTime = System.currentTimeMillis() - startTime;

        matrix.postRotate(30 * elapsedTime/1000);        // rotate 30° every second
        matrix.postTranslate(100 * elapsedTime/1000, 0); // move 100 pixels to the right
        // other transformations...

        canvas.concat(matrix);        // call this before drawing on the canvas!!

        canvas.drawPath(path, paint); // draw on canvas

        if(elapsedTime < animationDuration)
            this.postInvalidateDelayed( 1000 / framesPerSecond);
    }

}
 44
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-04 15:31:41

Prueba esto:

class PathDrawable extends Drawable implements AnimatorUpdateListener  {
    private Path mPath;
    private Paint mPaint;
    private ValueAnimator mAnimator;

    public PathDrawable() {
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setColor(0xffffffff);
        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Style.STROKE);
    }

    public void startAnimating() {
        Rect b = getBounds();
        mAnimator = ValueAnimator.ofInt(-b.bottom, b.bottom);
        mAnimator.setDuration(1000);
        mAnimator.addUpdateListener(this);
        mAnimator.start();
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawPath(mPath, mPaint);
    }

    @Override
    public void setAlpha(int alpha) {
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        mPath.reset();
        Rect b = getBounds();
        mPath.moveTo(b.left, b.bottom);
        mPath.quadTo((b.right-b.left)/2, (Integer) animator.getAnimatedValue(), b.right, b.bottom);
        invalidateSelf();
    }
}

Para probarlo agregue en su método onCreate:

TextView view = new TextView(this);
view.setText("click me");
view.setTextColor(0xffcccccc);
view.setGravity(Gravity.CENTER);
view.setTextSize(48);
final PathDrawable d = new PathDrawable();
view.setBackgroundDrawable(d);
OnClickListener l = new OnClickListener() {
    @Override
    public void onClick(View v) {
        d.startAnimating();
    }
};
view.setOnClickListener(l);
setContentView(view);
 20
Author: pskink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-04 15:33:15

Puedes crear un PathMeasure para tu ruta y determinar su longitud:

private PathMeasure pathMeasure; // field

// After you've created your path
pathMeasure = new PathMeasure(path, false); 
pathLength = pathMeasure.getLength();

Luego puedes obtener un punto específico en la ruta usando getPosTan () dentro, digamos, del oyente de actualización de ValueAnimator:

final float[] position = new float[2]; // field

// Inside your animation's update method, where dt is your 0..1 animated fraction
final float distance = dt * pathLength;
pathMeasure.getPosTan(distance, position, null);

// If using onDraw you'll need to tell the view to redraw using the new position
invalidate(); 

Luego puede hacer uso de la posición en onDraw (o lo que sea).

canvas.drawCircle(position[0], position[1], radius, paint);

Las ventajas de este enfoque es que es sencillo, no requiere matemáticas gruesas y funciona en todas las API.

Si usa API 21+, puede usar un ValueAnimator y pasar un Ruta para utilizar sus posiciones, que es más simple. Ejemplo ASÍ pregunta.

 1
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:39