[Trident] Flicker/Jump of interpolated property value
See original GitHub issueVersion of Radiance (current development is 3.5-SNAPSHOT)
Only trident is used
Sub-project (Neon, Trident, Substance, Flamingo, …)
Trident 3.0.0 https://mvnrepository.com/artifact/org.pushing-pixels/radiance-trident/3.0.0
Version of Java (current minimum is 9)
adoptjdk jdk-11.0.2+9
Version of OS
Betriebsystemname Microsoft Windows 10 Enterprise Version 10.0.18363 Build 18363
The issue you’re experiencing (expected vs actual, screenshot, stack trace etc)
My timeline creates a jump/flicker in the interpolated property that I cannot explain.
SSCCE:
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);
}
}
}
Description with sscce also here on stackoverflow
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)
Top Results From Across the Web
Trident 1.1 – interpolating properties - Pushing Pixels
This entry is going to talk about the most basic capability of Trident – interpolating properties of Java objects.
Read more >get-interpolated-asset-property-values - AWS Documentation
Description. Get interpolated values for an asset property for a specified time interval, during a period of time. If your time series is...
Read more >Can Stylus interpolate for a property value rather than a ...
I wonder if there is a workaround. Is there a way (in Stylus) for a Mixin (or another construct) to generate different variable...
Read more >Modelling of rent prices - which interpolation method to use?
I'd like to use this data to create surface of rent prices for the whole country and use this information as a proxy...
Read more >Interpolating Scattered Data - MATLAB & Simulink - MathWorks
Scattered data consists of a set of points X and corresponding values V ... The Method property represents the interpolation method that performs...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks for reporting this. In the future, the best place to file bugs is right here, as I don’t monitor StackOverflow for Radiance questions.
This is interesting. It’s because of the underlying assumption that the
TimelineEase
always maps the [0.0-1.0] interval without “warping” the end points. In this particular case, during each animation loop, the customFullSine
is used to remap that interval based on the sphere offset, but during the loop reset, the “end” points are not mapped.This is a valid use case. Will address.