javaFX8初探(动画和视觉效果)

52 篇文章 0 订阅
47 篇文章 3 订阅

你可以使用JavaFX很快的开发应用并且给用户带来丰富的用户体验。在这一个小节,我们使用非常少的代码创建一个动态且有复杂效果的

应用:五彩缤纷的圆圈,如下图所示:

 

 

下面这个图显示了场景图形,有分支的节点代表了Group类的实例,没有分支也就是叶子节点代表了Rectangle和Circle类的实例:

 

创建应用:

建立一个JavaFX项目

建立一个java文件,命名ColorfulCircles ,代码如下所示:

public class ColorfulCircles extends Application {
 
    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 600, Color.BLACK);
        primaryStage.setScene(scene);

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


 

这个应用比较合适实用group作为场景的根节点。group的大小取决于里面节点的大小。然而,通常我们希望我们场景的大小会跟随舞台(

窗口)的大小改变而改变,如果是这样的话,我们可以使用可变大小的布局节点,就上之前文章中登陆表单那样。

你现在已经可以运行这个应用了,你应该在途中经常时不时的看一下结果。如果运行出错了,可以停下看看一下代码。现在运行的结果是

一个黑色的窗口。

 

添加图形

下面,我们添加30个圆圈

Group circles = new Group();
for (int i = 0; i < 30; i++) {
   Circle circle = new Circle(150, Color.web("white", 0.05));
   circle.setStrokeType(StrokeType.OUTSIDE);
   circle.setStroke(Color.web("white", 0.16));
   circle.setStrokeWidth(4);
   circles.getChildren().add(circle);
}
root.getChildren().add(circles);


 

这段代码创建了一个Group,名字是circles,然后用一个循环添加了30个圆圈到这个group,每个圆圈的半径是150,颜色是白色,不透明

度是5%,这意味着这个圆圈几乎是透明的。

然后为这些圆圈创建一个边框,使用stroke,这里是边框为 外边框,白色 ,不透明度为16%,宽度是4.所以这个边框比圆圈应该更明亮。

最后把这些圆圈添加到root节点里,这只是一个临时的结构,之后我们会修改场景图形是它表现的和上面说的一致。

运行应用,如下图所示:

 

 

添加视觉效果

为圆圈加上盒子模糊效果
circles.setEffect(new BoxBlur(10, 10, 3));
这段代码设置模糊半径10像素宽 和 10像素高,模糊迭代3,是它接近于高斯模糊,这样会使得圆的边缘过度更加平滑。运行代码如下图所

示:

 

设置背景渐变

创建一个矩形,设置它为线性渐变,代码如下:

Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(),
     new LinearGradient(0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE, new 
         Stop[]{
            new Stop(0, Color.web("#f8bd55")),
            new Stop(0.14, Color.web("#c0fe56")),
            new Stop(0.28, Color.web("#5dfbc1")),
            new Stop(0.43, Color.web("#64c2f8")),
            new Stop(0.57, Color.web("#be4af7")),
            new Stop(0.71, Color.web("#ed5fc2")),
            new Stop(0.85, Color.web("#ef504c")),
            new Stop(1, Color.web("#f2660f")),}));
colors.widthProperty().bind(scene.widthProperty());
colors.heightProperty().bind(scene.heightProperty());
root.getChildren().add(colors);


 

这段代码创建了一个矩形,命名为colores。这个矩形的大小和场景的大小一致,开始于左上角(0,1),结束于右上角(1,0),true表示

线性渐变保持比例,NO_CYCLE表示渐变不会重复,Stop[]序列表示在特定的地方渐变。

接下来的两行代码,使得渐变会跟随窗口的变化而变化。最后把这个颜色的渐变添加到root节点:

运行应用如下图所示:

 

 

目前场景图形如下图所示:

 

应用混合模式:

接下来,我们为圆圈添加颜色,并且通过一个叠加混合效果使场景变暗,

1:找到下面的代码:

root.getChildren().add(colors);
root.getChildren().add(circles);


2:用下面的代码替换第一步中的代码:

Group blendModeGroup = 
    new Group(new Group(new Rectangle(scene.getWidth(), scene.getHeight(),
        Color.BLACK), circles), colors);
colors.setBlendMode(BlendMode.OVERLAY);
root.getChildren().add(blendModeGroup);


 


blendModeGroup的架构是叠加混合,这个group有两个子节点,第一个是新的Group,这个group是一个黑色的矩形和之前创建的圆圈group

,第二个是之前创建的颜色矩形,

setBlendMode方法使得叠加混合应用于颜色矩形最后把这个group添加到场景中。

运行应用,如下图所示:

 

 

添加动画:

最后的步骤就是使用JavaFX动画移动这些圆圈
添加如下代码:

Timeline timeline = new Timeline();
for (Node circle: circles.getChildren()) {
    timeline.getKeyFrames().addAll(
        new KeyFrame(Duration.ZERO, // set start position at 0
            new KeyValue(circle.translateXProperty(), random() * 800),
            new KeyValue(circle.translateYProperty(), random() * 600)
        ),
        new KeyFrame(new Duration(40000), // set end position at 40s
            new KeyValue(circle.translateXProperty(), random() * 800),
            new KeyValue(circle.translateYProperty(), random() * 600)
        )
    );
}
// play 40s of animation
timeline.play();


 

动画是靠时间轴来驱动的,所以这段代码里创建了一个时间轴,然后使用for循环为每个圆圈添加了两个关键帧。第一个关键帧在0秒的时

候使用translateXProperty 和 translateYProperty 属性确定在窗口中的一个随机的位置。第二个关键帧在40秒后做相同的事情。所以当

时间轴开始后,每个圆圈都会在40秒内从一个位置移动到另一个位置。

运行应用如下图所示:

 

全部代码如下所示:

package com.chu.helloworld;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.BoxBlur;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ColorfulCircles extends Application {

	@Override
	public void start(Stage primaryStage) {
		Group root = new Group();

		Group circles = new Group();
		for (int i = 0; i < 30; i++) {
			Circle circle = new Circle(150, Color.web("white", 0.05));
			circle.setStrokeType(StrokeType.OUTSIDE);
			circle.setStroke(Color.web("white", 0.16));
			circle.setStrokeWidth(4);
			circles.getChildren().add(circle);
		}
		circles.setEffect(new BoxBlur(10, 10, 3));

		Scene scene = new Scene(root, 800, 600, Color.BLACK);
		primaryStage.setScene(scene);

		Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(),
				new LinearGradient(0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE,
						new Stop[] { new Stop(0, Color.web("#f8bd55")),
								new Stop(0.14, Color.web("#c0fe56")),
								new Stop(0.28, Color.web("#5dfbc1")),
								new Stop(0.43, Color.web("#64c2f8")),
								new Stop(0.57, Color.web("#be4af7")),
								new Stop(0.71, Color.web("#ed5fc2")),
								new Stop(0.85, Color.web("#ef504c")),
								new Stop(1, Color.web("#f2660f")), }));

		colors.widthProperty().bind(scene.widthProperty());
		colors.heightProperty().bind(scene.heightProperty());

		Group blendModeGroup = new Group(new Group(new Rectangle(
				scene.getWidth(), scene.getHeight(), Color.BLACK), circles),
				colors);
		
		colors.setBlendMode(BlendMode.OVERLAY);
		
		root.getChildren().add(blendModeGroup);
		
		
		Timeline timeline = new Timeline();
		for (Node circle: circles.getChildren()) {
		    timeline.getKeyFrames().addAll(
		        new KeyFrame(Duration.ZERO, // set start position at 0
		            new KeyValue(circle.translateXProperty(), Math.random() * 800),
		            new KeyValue(circle.translateYProperty(), Math.random() * 600)
		        ),
		        new KeyFrame(new Duration(40000), // set end position at 40s
		            new KeyValue(circle.translateXProperty(), Math.random() * 800),
		            new KeyValue(circle.translateYProperty(), Math.random() * 600)
		        )
		    );
		}
		// play 40s of animation
		timeline.play();
		
		primaryStage.show();
	}

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


 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值