英文:
android rotate animation reduce calculations and make animation smooth
问题
我正在尝试绘制一个自定义旋转动画。这是我的代码输出。
基本上每个圆都有小的子圆。唯一的问题是,有时动画会跳过一些帧,看起来断断续续的。我猜想,由于这个计算是耗时的,所以会丢失一些帧。
我的问题是,如何最好地改进这个问题并保持动画的流畅性。
是否可能仅计算第一帧,然后旋转画布,以便我们可以减少计算量?
@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);
}
}
}
动画器
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();
}
英文:
I'm trying to draw a custom rotating animation. This is the output of my code.
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();
}
答案1
得分: 2
你可以预先计算小圆的中心坐标,当shiftAngle = 0
,然后将它们存储在数组中。你可以首先绘制它们,然后使用以下公式旋转它们Math.PI / 180
。
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;
因为Math.sin(Math.PI / 180)
和Math.cos(Math.PI / 180)
都是常数。它们可以提前在循环之外计算。
通过这种方法,你可以将正弦和余弦计算从循环中移出。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论