web-dev-qa-db-fra.com

Comment animer un chemin sur un canevas - android

Est-il possible d'attacher un animateur à un chemin? Existe-t-il un autre moyen de dessiner sur des lignes animées sur toile? J'ai cherché avant de poster, mais il n'y a rien à ce sujet. Dans deux autres articles ici et ici il existe des solutions de contournement et ne me conviennent pas.

Je poste mon code dans la méthode onDraw pour spécifier exactement ce que je veux.

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

Des idées????

31
karvoynistas

Vous pouvez transformer votre toile par le temps, à savoir:

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

}
46
Simon

essaye ça:

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

pour le tester, ajoutez votre méthode 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);
21
pskink

Vous pouvez créer un PathMeasure pour votre chemin et déterminer sa longueur:

private PathMeasure pathMeasure; // field

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

Vous pouvez ensuite obtenir un point spécifique sur le chemin en utilisant getPosTan () à l'intérieur, par exemple, l'écouteur de mise à jour 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(); 

Vous pouvez ensuite utiliser la position dans onDraw (ou autre).

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

Les avantages de cette approche sont qu'elle est simple, ne nécessite pas de calculs volumineux et fonctionne sur toutes les API.

Si vous utilisez l'API 21+, vous pouvez utiliser un ValueAnimator et passer un chemin pour utiliser ses positions, ce qui est plus simple. Exemple SO question .

1
Tom