当前位置: 首页 > news >正文

【JAVAFX】在屏幕上出现旋转随机小彩球效果

直接上代码

package sample;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
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.stage.StageStyle;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

// 主类,继承自Application,是JavaFX应用程序的入口
public class Main extends Application {
    // 定义常量,表示火花的数量为100个
    private static final int SPARK_COUNT = 100;
    // 用于存储所有火花对象的列表
    private List<Spark> sparks = new ArrayList<>();
    // 用于绘图的画布对象
    private Canvas canvas;
    // 绕X轴的旋转角度,初始化为0
    private double rotationAngleX = 0;
    // 绕Y轴的旋转角度,初始化为0
    private double rotationAngleY = 0;
    // 旋转速度,用于控制角度的变化速率
    private double rotationSpeed = 0.01;
    //在屏幕的什么范围内生成
    private Integer xZone=1920;
    private Integer yZone=1000;

    // JavaFX应用程序启动时调用的方法
    @Override
    public void start(Stage primaryStage) throws Exception {
        // 创建一个根节点Group,用于组织场景中的所有节点
        Group root = new Group();
        // 创建一个宽度为800,高度为600的画布
        canvas = new Canvas(xZone, yZone);
        // 将画布添加到根节点中
        root.getChildren().add(canvas);

        // 循环创建100个火花对象,并添加到sparks列表中
        for (int i = 0; i < SPARK_COUNT; i++) {
            sparks.add(new Spark(xZone,yZone));
        }

        // 创建一个动画定时器,用于定时更新和绘制画面
        AnimationTimer timer = new AnimationTimer() {
            // 每次定时器触发时调用的方法
            @Override
            public void handle(long now) {
                // 获取画布的绘图上下文,用于绘制图形
                GraphicsContext gc = canvas.getGraphicsContext2D();
                // 清空画布上的内容
                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

                // 保存当前的绘图状态,以便后续恢复
                gc.save();

                // 将绘图原点平移到画布的中心
                gc.translate(canvas.getWidth() / 2, canvas.getHeight() / 2);

                // 增加绕X轴和Y轴的旋转角度
                rotationAngleX += rotationSpeed;
                rotationAngleY += rotationSpeed;

                // 遍历所有的火花对象
                for (Spark spark : sparks) {
                    // 更新火花的状态(例如透明度)
                    spark.update();
                    // 计算火花在3D空间中的初始坐标(相对于画布中心的偏移)
                    double x3d = spark.x - canvas.getWidth() / 2;
                    double y3d = spark.y - canvas.getHeight() / 2;
                    double z = spark.depth;

                    // 进行绕X轴的旋转计算,更新Y和Z坐标
                    double newY = y3d * Math.cos(rotationAngleX) - z * Math.sin(rotationAngleX);
                    z = y3d * Math.sin(rotationAngleX) + z * Math.cos(rotationAngleX);
                    y3d = newY;

                    // 进行绕Y轴的旋转计算,更新X和Z坐标
                    double newX = x3d * Math.cos(rotationAngleY) + z * Math.sin(rotationAngleY);
                    z = -x3d * Math.sin(rotationAngleY) + z * Math.cos(rotationAngleY);
                    x3d = newX;

                    // 计算透视变换的因子,用于模拟3D效果
                    double factor = 1000.0 / (1000.0 + z);
                    // 计算在屏幕上的X坐标
                    double screenX = x3d * factor + canvas.getWidth() / 2;
                    // 计算在屏幕上的Y坐标
                    double screenY = y3d * factor + canvas.getHeight() / 2;
                    // 计算在屏幕上显示的火花大小
                    double size = spark.size * factor;

                    // 设置绘图颜色,根据火花的颜色和透明度进行调整
                    gc.setFill(spark.color.deriveColor(0, 1, 1, spark.alpha));
                    // 在计算后的坐标位置绘制火花(一个椭圆)
                    gc.fillOval(screenX - size / 2, screenY - size / 2, size, size);
                }

                // 移除透明度为0(即已经消失)的火花
                sparks.removeIf(spark -> spark.alpha == 0);
                // 如果火花数量不足100个,添加新的火花
                while (sparks.size() < SPARK_COUNT) {
                    sparks.add(new Spark(xZone,yZone));
                }

                // 恢复之前保存的绘图状态
                gc.restore();
            }
        };

        // 启动动画定时器
        timer.start();

        // 设置窗口的样式为透明
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        // 创建一个场景,包含根节点,宽度为800,高度为600,背景透明
        Scene scene = new Scene(root, xZone, yZone, Color.TRANSPARENT);
        // 将场景设置到主舞台上
        primaryStage.setScene(scene);
        // 显示主舞台
        primaryStage.show();
    }

    // 应用程序的入口点,启动JavaFX应用程序
    public static void main(String[] args) {
        launch(args);
    }
}

// 火花类,用于表示一个火花对象
class Spark {
    // 火花在画布上的X坐标
    double x;
    // 火花在画布上的Y坐标
    double y;
    // 火花的大小
    double size;
    // 火花的颜色
    Color color;
    // 火花的透明度
    double alpha;
    // 火花在3D空间中的深度值
    double depth;

    // 构造方法,用于初始化火花的属性
    public Spark(int xZone,int yZone) {
        Random random = new Random();
        // 随机生成X坐标,范围在0到800之间
        x = random.nextInt(xZone);
        // 随机生成Y坐标,范围在0到600之间
        y = random.nextInt(yZone);
        // 随机生成大小,范围在2到102之间
        size = random.nextDouble() * 100 + 10;
        // 随机生成颜色
        color = Color.color(random.nextDouble(), random.nextDouble(), random.nextDouble());
        // 初始透明度为1.0(完全不透明)
        alpha = 1.0;
        // 随机生成深度值,范围在0到1000之间
        depth = random.nextDouble() * 1000;
    }

    // 更新火花状态的方法,主要是减少透明度
    public void update() {
        alpha -= 0.01;
        if (alpha < 0) {
            alpha = 0;
        }
    }
}
http://www.dtcms.com/a/63159.html

相关文章:

  • Acknowledgment.nack方法重试消费kafka消息异常
  • 【算法】经典排序算法介绍+代码示例
  • NAFNet:Simple Baselines for Image Restoration
  • 懒加载(Lazy Loading):原理、实现与优化策略
  • Windows系统编程项目(四)窗口管理器
  • 典型相关分析(CCA)探索多维数据间的深层关系:基于Matlab
  • 第一章:像素学徒的觉醒
  • 网络信息安全专业(710207)网络安全攻防实训室建设方案
  • HTML <head> 元素详解:网页头部的关键组成部分
  • rpmlib(SetVersions) is needed by can-uilts-v2019.00.0-alt1.aarch64
  • uniapp简单table表
  • vue项目的琐碎点
  • Vue | 开学第一课!零基础教程
  • PostgreSQL17(最新版)安装部署
  • 【三维重建】Proc-GS:使用3DGS的程序性城市建筑生成
  • c++介绍信号六
  • react基础语法视图层类组件
  • 计算机毕业设计:驾校综合信息系统
  • 基于SpringBoot实现旅游酒店平台功能八
  • MCU与SFU:实时音视频通信架构的对比
  • 使用STM32CubeMX配置定时器中断实现LED每秒闪烁一次(STM32G070CBT6)
  • 【Yonghong 企业日常问题07 】 东方通TongWeb替代Tomcat的实战指南!
  • ubuntu中用docker下载opengauss
  • 利用 ECB 加密 json并压测接口,输出测试报告
  • 计算机网络基础:PKI(公钥基础设施)
  • vue el-select 省市区三级联动 vue + element-ui使用第三方插件实现省市区三级联动
  • BambuStudio学习笔记:MinAreaBoundigBox
  • 远程手机遥控开关原理及应用
  • 如何安全处置旧设备?
  • Java 无 GUI 浏览器:HtmlUnit 入门及实战 [特殊字符]