0

I would like to fade in and fadeout a circle in a javafx canvas. I can move a circle from one part of the screen to another but i just can't seem to get this object to fade in and out.

Below is the code i used for moving a circle from one part of the screen to the other

public class AnimatedCircleOnCanvas extends Application {
    public static final double W = 200; // canvas dimensions.
    public static final double H = 200;

    public static final double D = 20;  // diameter.

    @Override public void start(Stage stage) {
        DoubleProperty x  = new SimpleDoubleProperty();
        DoubleProperty y  = new SimpleDoubleProperty();

        Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(0),
                    new KeyValue(x, 0),
                    new KeyValue(y, 0)
            ),
            new KeyFrame(Duration.seconds(3),
                    new KeyValue(x, W - D),
                    new KeyValue(y, H - D)
            )
        );
        timeline.setAutoReverse(true);
        timeline.setCycleCount(Timeline.INDEFINITE);

        final Canvas canvas = new Canvas(W, H);
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                GraphicsContext gc = canvas.getGraphicsContext2D();
                gc.setFill(Color.CORNSILK);
                gc.fillRect(0, 0, W, H);
                gc.setFill(Color.FORESTGREEN);
                gc.fillOval(
                    x.doubleValue(),
                    y.doubleValue(),
                    D,
                    D
                );
            }
        };

        stage.setScene(
            new Scene(
                new Group(
                    canvas
                )
            )
        );
        stage.show();

        timer.start();
        timeline.play();
    }

    public static void main(String[] args) { launch(args); }
}  

Your help is greatly appreciated

Lycon
  • 2,369
  • 2
  • 15
  • 16
  • Original code source: [Moving shapes in JavaFX Canvas](http://stackoverflow.com/questions/21396055/moving-shapes-in-javafx-canvas). – jewelsea Mar 12 '15 at 16:55

1 Answers1

3

Animate a DoubleProperty for the opacity in values ranging from 1 to 0 in exactly the same way as you animated the properties for x and y, and then use Color.deriveColor(...) to set the color based on the changing property:

import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class FadeCircleOnCanvas extends Application {
    public static final double W = 200; // canvas dimensions.
    public static final double H = 200;

    public static final double D = 20;  // diameter.

    @Override public void start(Stage stage) {
        DoubleProperty opacity  = new SimpleDoubleProperty();

        Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(0),
                    new KeyValue(opacity, 1)
            ),
            new KeyFrame(Duration.seconds(3),
                    new KeyValue(opacity, 0)
            )
        );
        timeline.setAutoReverse(true);
        timeline.setCycleCount(Timeline.INDEFINITE);

        final Canvas canvas = new Canvas(W, H);
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                GraphicsContext gc = canvas.getGraphicsContext2D();
                gc.setFill(Color.CORNSILK);
                gc.fillRect(0, 0, W, H);
                gc.setFill(Color.FORESTGREEN.deriveColor(0, 1, 1, opacity.get()));
                gc.fillOval(
                    W/2,
                    H/2,
                    D,
                    D
                );
            }
        };

        stage.setScene(
            new Scene(
                new Group(
                    canvas
                )
            )
        );
        stage.show();

        timer.start();
        timeline.play();
    }

    public static void main(String[] args) { launch(args); }
}  

In general, I prefer not to use a Canvas for this, and just to use Shape instances placed in a Pane. Then you can directly change the pre-defined properties of the Shape, or in many cases use specific pre-defined animations (TranslateTransition or FadeTransition for example).

Here's the same example using this technique:

import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

    public class FadeCircleOnCanvas extends Application {
        public static final double W = 200; // canvas dimensions.
        public static final double H = 200;

        public static final double D = 20;  // diameter.

        @Override public void start(Stage stage) {

            Circle circle = new Circle(W/2, H/2, D, Color.FORESTGREEN);

            FadeTransition fade = new FadeTransition(Duration.seconds(3), circle);
            fade.setFromValue(1);
            fade.setToValue(0);
            fade.setAutoReverse(true);
            fade.setCycleCount(Timeline.INDEFINITE);

            Pane pane = new Pane(circle);

            stage.setScene(
                new Scene(
                    pane, W, H, Color.CORNSILK
                )
            );
            stage.show();

            fade.play();
        }

        public static void main(String[] args) { launch(args); }
    }  
James_D
  • 201,275
  • 16
  • 291
  • 322
  • thanks. But i was wondering, how could you modify this method so that one circle fades in for a second and then another circle fades in just after. Or is it easier to implement this using a pane instead. – Lycon Mar 12 '15 at 17:19
  • 1
    It's all easier to implement with a pane. But it should be easy enough to adapt this either way. – James_D Mar 12 '15 at 17:41
  • i would also like to be able to fade in an object one at a time. For example, using a for loop to loop through each node and fading it in on the pane and waiting a second or two before fading in the next – Lycon Mar 12 '15 at 20:03
  • Then write the code to do so Lycon, StackOverflow is not a coding service. Consider adapting James' pane/node based solution and using a [SequentialTransition](http://docs.oracle.com/javase/8/javafx/api/javafx/animation/SequentialTransition.html). You can always ask new questions if you run into issues after trying to write the code. – jewelsea Mar 12 '15 at 20:33