【发布时间】:2020-09-29 21:40:30
【问题描述】:
通过trident,我创建了一个(看似)简单的动画。一些圆圈正在从底部移动到顶部,然后通过正弦插值再次返回:
动画本身似乎可以正常工作,但是有一两帧我的所有球体都闪烁到最高位置。
为什么会闪烁?谁在用看似错误的值调用setY 方法?
我制作了一个测试类来重现该行为。您需要radiance-trident 3.0 才能使其工作:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JDialog;
import javax.swing.JPanel;
import org.pushingpixels.trident.api.Timeline;
import org.pushingpixels.trident.api.Timeline.RepeatBehavior;
import org.pushingpixels.trident.api.ease.TimelineEase;
import org.pushingpixels.trident.api.swing.SwingRepaintTimeline;
public class MovingSpheresTest extends JDialog {
private final double sphereRadius = 3d;
private final double sphereCount = 12d;
private final double helixHeight = 100d;
private final double size = 200d;
private final double animationSpeed = 0.5d;
private List<CenteredSphere> spheres;
private SwingRepaintTimeline repaintTimeline;
private final JPanel contentPanel = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintFrame((Graphics2D) g);
}
private void paintFrame(Graphics2D g) {
Graphics2D create = (Graphics2D) g.create();
try {
create.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
create.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
create.setColor(Color.BLACK);
for (CenteredSphere centeredSphere : spheres) {
create.fill(centeredSphere);
}
} finally {
create.dispose();
}
}
};
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
MovingSpheresTest dialog = new MovingSpheresTest();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the dialog.
*/
public MovingSpheresTest() {
setBounds(100, 100, 450, 300);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
getContentPane().add(contentPanel, BorderLayout.CENTER);
installSpheres();
installRepaintTimeline();
}
private void installSpheres() {
double helixRadius = helixHeight / 2;
double effectiveWidth = size - (2 * sphereRadius);
double sphereDistance = effectiveWidth / (sphereCount - 1);
double sphereCenterX = sphereRadius;
double sphereCenterY = size / 2d;
double sphereCenterYInitial = sphereCenterY - helixRadius;
spheres = new ArrayList<>();
for (int sphereIndex = 0; sphereIndex < sphereCount; sphereIndex++) {
CenteredSphere sphere = new CenteredSphere(sphereCenterX, sphereRadius);
spheres.add(sphere);
sphereCenterX += sphereDistance;
Timeline.builder()
.addPropertyToInterpolate(Timeline.<Double>property("y").on(sphere).from(sphereCenterYInitial)
.to(sphereCenterY + helixRadius))
.setEase(new FullSine((float) (sphereIndex * 2 * Math.PI / sphereCount)))
.setDuration((long) (animationSpeed * 3000d)).playLoop(RepeatBehavior.LOOP);
}
}
private class FullSine implements TimelineEase {
private float horizontalOffset;
private FullSine(float horizontalOffset) {
this.horizontalOffset = horizontalOffset;
}
@Override
public float map(float durationFraction) {
return ((float) Math.sin(durationFraction * Math.PI * 2f + horizontalOffset) + 1f) / 2f;
}
}
private void installRepaintTimeline() {
repaintTimeline = SwingRepaintTimeline.repaintBuilder(contentPanel).build();
repaintTimeline.playLoop(RepeatBehavior.LOOP);
}
public class CenteredSphere extends Ellipse2D.Double {
private double sphereCenterX;
private double sphereRadius;
public CenteredSphere(double sphereCenterX, double sphereRadius) {
this.sphereCenterX = sphereCenterX;
this.sphereRadius = sphereRadius;
}
public void setY(double y) {
setFrameFromCenter(sphereCenterX, y, sphereCenterX + sphereRadius, y + sphereRadius);
}
}
}
【问题讨论】:
标签: java swing animation trident