javaFx清空缓存动画特效

package com.excellent.archimedes.fx.controller;

/**

* @author zhaoyong

* @Date 2024/10/12

* @Description

*/

import com.alibaba.fastjson.JSON;

import com.excellent.archimedes.util.AlertUtils;

import com.excellent.archimedes.util.UIViewContextUtils;

import javafx.animation.*;

import javafx.event.ActionEvent;

import javafx.fxml.FXML;

import javafx.fxml.Initializable;

import javafx.geometry.Point2D;

import javafx.scene.canvas.Canvas;

import javafx.scene.canvas.GraphicsContext;

import javafx.scene.control.Button;

import javafx.scene.layout.Pane;

import javafx.scene.paint.Color;

import javafx.util.Duration;

import org.apache.commons.lang3.StringUtils;

import org.springframework.stereotype.Component;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import java.util.ResourceBundle;

@Component

public class SeeCacheController implements Initializable {

/* ===================== 以下为原控件 ===================== */

@FXML private Pane userPane;

@FXML private Button reset;

@FXML private Button returnHomepage;

/* ===================== 新增动画节点 ===================== */

private Canvas animCanvas; // 360°圆环+碎片

private GraphicsContext gc;

private final double RING_RADIUS = 80; // 圆环半径

private final double RING_STROKE = 6; // 圆环粗细

private final int FRAG_COUNT = 12; // 碎片数量

private final List<Fragment> fragments = new ArrayList<>();

@Override

public void initialize(URL location, ResourceBundle resources) {

/* 把 Canvas 放到原 Pane 里,居中 */

animCanvas = new Canvas(300, 300);

userPane.getChildren().add(animCanvas);

animCanvas.setLayoutX(20); // 自己按实际布局微调

animCanvas.setLayoutY(30);

gc = animCanvas.getGraphicsContext2D();

}

/* ===================== 原业务方法不动 ===================== */

@FXML void returnHome(ActionEvent event) { UIViewContextUtils.subStage.close(); }

@FXML void returnToHome(ActionEvent event) { UIViewContextUtils.subStage.hide(); }

@FXML

void checkCache(ActionEvent event) {

try {

String cacheContent = JSON.toJSONString(UIViewContextUtils.subStage.getUserData());

if (StringUtils.isNotBlank(cacheContent) && !cacheContent.equals("null")) {

AlertUtils.alert("查看缓存", cacheContent);

} else {

AlertUtils.alert("查看缓存", "缓存已清空");

}

} catch (Exception e) {

e.printStackTrace();

}

}

/* ===================== 清空缓存 + 360°特效 ===================== */

@FXML

void clearCache(ActionEvent event) {

boolean go = AlertUtils.prompt("要清空缓存", "确定要清空缓存吗?");

if (!go) return;

initFragments(); // 生成 12 片扇形碎片

Timeline master = new Timeline(new KeyFrame(Duration.millis(16), e -> drawFrame())); // 60 fps

master.setCycleCount(Timeline.INDEFINITE);

master.play();

/* 3 秒后结束动画并真正清理 */

PauseTransition end = new PauseTransition(Duration.seconds(3));

end.setOnFinished(e -> {

master.stop();

fragments.clear();

gc.clearRect(0, 0, animCanvas.getWidth(), animCanvas.getHeight());

UIViewContextUtils.thirdSubStage.setUserData(null);

UIViewContextUtils.subStage.setUserData(null);

UIViewContextUtils.primaryStage.setUserData(null);

AlertUtils.alert("清空缓存", "缓存已清空完毕");

});

end.play();

}

/* ===================== 碎片内部类 ===================== */

private static class Fragment {

double startAngle; // 初始角度

double distance; // 当前已飞出距离

double speed; // 每帧飞出速度

double opacity; // 当前透明度

final double MAX_DIST = 120;

Fragment(double angle) {

this.startAngle = angle;

this.distance = 0;

this.speed = 2 + Math.random() * 2;

this.opacity = 1.0;

}

void fly() {

distance += speed;

opacity = Math.max(0, 1 - distance / MAX_DIST);

}

}

private void initFragments() {

fragments.clear();

for (int i = 0; i < FRAG_COUNT; i++) {

fragments.add(new Fragment(i * 360.0 / FRAG_COUNT));

}

}

/* ===================== 每帧绘制 ===================== */

private double ringAngle = 0;

private void drawFrame() {

gc.clearRect(0, 0, animCanvas.getWidth(), animCanvas.getHeight());

double cx = animCanvas.getWidth() / 2;

double cy = animCanvas.getHeight() / 2;

/* 1. 旋转圆环 */

ringAngle += 4;

gc.save();

gc.translate(cx, cy);

gc.rotate(ringAngle);

gc.setStroke(Color.rgb(30, 144, 255));

gc.setLineWidth(RING_STROKE);

gc.strokeOval(-RING_RADIUS, -RING_RADIUS, RING_RADIUS * 2, RING_RADIUS * 2);

/* 画 60 条刻度 */

for (int i = 0; i < 60; i++) {

double a = Math.toRadians(i * 6);

double len = (i % 5 == 0) ? 10 : 5;

gc.strokeLine(RING_RADIUS - len, 0, RING_RADIUS, 0);

gc.rotate(6);

}

gc.restore();

/* 2. 碎片向外飞 */

gc.setFill(Color.ORANGE);

fragments.removeIf(f -> f.opacity <= 0);

for (Fragment f : fragments) {

double rad = Math.toRadians(f.startAngle);

Point2D p = new Point2D(

cx + Math.cos(rad) * (RING_RADIUS * 0.7 + f.distance),

cy + Math.sin(rad) * (RING_RADIUS * 0.7 + f.distance));

gc.setGlobalAlpha(f.opacity);

gc.fillOval(p.getX() - 4, p.getY() - 4, 8, 8);

f.fly();

}

gc.setGlobalAlpha(1.0);

}

}

相关推荐
惊讶的猫13 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
jiunian_cn14 小时前
【Redis】渐进式遍历
数据库·redis·缓存
jiunian_cn15 小时前
【Redis】数据库管理操作
数据库·redis·缓存
難釋懷16 小时前
秒杀优化-基于阻塞队列实现秒杀优化
redis·缓存
清水白石00816 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
无尽的沉默17 小时前
Redis下载安装
数据库·redis·缓存
yuanmenghao17 小时前
Linux 性能实战 | 第 10 篇 CPU 缓存与内存访问延迟
linux·服务器·缓存·性能优化·自动驾驶·unix
消失的旧时光-194318 小时前
第十六课实战:分布式锁与限流设计 —— 从原理到可跑 Demo
redis·分布式·缓存
时艰.19 小时前
java性能调优 — 高并发缓存一致性
java·开发语言·缓存
JFSJHFZJ19 小时前
清理手机顽固缓存,轻松释放几GB空间
缓存·智能手机