1

I'm trying to draw a custom rotating animation. This is the output of my code.

enter image description here

Basically every circle has small sub circles. Only issue is, sometimes animation skip some frames and animation looks broken. My guess is since this calculation is time consuming some frames are missing.

My question is what is the best way to improve this and keep animation smooth. Is it possible to just calculate for first frame and rotate the canvas so we can reduce the calculations?

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);    
    int startRadius = 20;
    int endRadius = 400;
    int circleCount = 20;
    int circleDistance = (int) (((endRadius - startRadius) / (float) circleCount));

    for (int i = 0; i < circleCount; i++) {
        int radius = startRadius + i * circleDistance;
        canvas.drawCircle(center.x, center.y, radius, mPaint);

        int subCircles=i+1;
        double angleSegment = Math.PI * 2 / subCircles;
        for (int segment = 0; segment < subCircles; segment++) {
            double angle = angleSegment * segment + shiftAngle;
            double x = Math.cos(angle) * radius;
            double y = Math.sin(angle) * radius;
            canvas.drawCircle((float) (x + center.x), (float) (y + center.y), 6, pointPaint);
        }

    }
}

Animator

public void startAnim() {
    rotateAnim = ValueAnimator.ofInt(0, 100);
    rotateAnim.setDuration(1000);
    rotateAnim.setInterpolator(new LinearInterpolator());
    rotateAnim.addUpdateListener(animation -> {
        shiftAngle += Math.PI / 180;
        View.this.invalidate();
    });
    rotateAnim.setRepeatCount(ValueAnimator.INFINITE);
    rotateAnim.start();
}
while true
  • 816
  • 1
  • 11
  • 26

1 Answers1

2

You can precalculate the center coordinates of the small circles at shiftAngle = 0 and store them in arrays. You can draw them first and then rotate them Math.PI / 180 with the following formula.

 newX = Math.cos(Math.PI / 180) * x - Math.sin(Math.PI / 180) * y;
 newY = Math.sin(Math.PI / 180) * x + Math.cos(Math.PI / 180) * y;

Since Math.sin(Math.PI / 180) and Math.cos(Math.PI / 180) are constants. They can be calculated outside the loop in advance.

You can push sin and cos calculations out of the loop by doing this.

  • thanks.i see with this i could save some computational time.but i still wonder is it possible to draw and just rotate the drawn canvas without calculating for another frame – while true Jul 26 '20 at 08:43