You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中基于贝塞尔曲线实现逐点绘制数字的动画效果

Java 贝塞尔曲线数字绘制动画实现方案

1. 对应JS动画逻辑的Java实现

你提供的JS animate 函数核心是靠 requestAnimationFrame 实现帧同步的动画调度,Java 生态里推荐用 JavaFX 做GUI绘图,对应的等价API是 AnimationTimer,实现代码如下:

import javafx.animation.AnimationTimer;
import java.util.function.Function;
import java.util.function.Consumer;

public class BezierAnimTool {
    /**
     * 通用动画执行方法
     * @param timing 缓动函数:入参是时间占比[0,1],返回实际绘制进度[0,1]
     * @param draw 绘制回调:入参是当前绘制进度
     * @param durationMs 动画总时长,单位毫秒
     */
    public static void run(Function<Double, Double> timing, Consumer<Double> draw, long durationMs) {
        long startTimeNano = System.nanoTime();
        new AnimationTimer() {
            @Override
            public void handle(long nowNano) {
                // 计算时间占比
                double timeFraction = (nowNano - startTimeNano) / (durationMs * 1_000_000.0);
                timeFraction = Math.min(timeFraction, 1.0);
                // 计算映射后的绘制进度
                double progress = timing.apply(timeFraction);
                draw.accept(progress);
                // 动画结束停止调度
                if (timeFraction >= 1.0) {
                    stop();
                }
            }
        }.start();
    }
}

如果用Swing实现,替换为 javax.swing.Timer 做帧调度即可,核心逻辑完全一致。


2. 贝塞尔曲线数字绘制核心实现

2.1 预定义数字的贝塞尔路径

首先需要为每个数字配置轮廓的贝塞尔曲线锚点和控制点,示例如下:

import javafx.scene.shape.Path;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.CubicCurveTo;

// 示例:定义数字0的三次贝塞尔闭合路径
Path num0Path = new Path(
    new MoveTo(50, 20), // 起点
    new CubicCurveTo(80, 20, 100, 40, 100, 70), // 三次贝塞尔段:两个控制点+终点
    new CubicCurveTo(100, 100, 80, 120, 50, 120),
    new CubicCurveTo(20, 120, 0, 100, 0, 70),
    new CubicCurveTo(0, 40, 20, 20, 50, 20)
);

2.2 按进度绘制路径

需要先计算路径总长度,再根据当前进度截取对应长度的路径片段绘制,JavaFX可借助 PathTransition 快速实现路径截取,也可自己实现路径采样计算。示例调用代码:

// 缓动函数示例:ease-in-out 三次方缓动,视觉效果更自然
Function<Double, Double> easeInOut = time -> {
    return time < 0.5 ? 4 * time * time * time : 1 - Math.pow(-2 * time + 2, 3) / 2;
};

// 启动动画,总时长1500毫秒
BezierAnimTool.run(easeInOut, progress -> {
    // 清理画布
    gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
    // 截取progress比例的路径绘制
    drawPathPart(num0Path, progress);
}, 1500);

3. 平滑绘制效果实现要点

  • 点位平滑拟合:离散的轮廓点位不要直接用直线连接,用三次贝塞尔曲线做拟合,两个锚点之间的控制点根据前后锚点的切线方向计算,消除尖锐拐角
  • 缓动优化:不要使用线性进度映射,使用贝塞尔缓动函数控制绘制速度,开头慢加速、结尾慢减速,避免动画突兀
  • 长度校准:按路径总长度分配绘制进度,不要按点位数量分配,避免短路径绘制快、长路径绘制慢的不均问题
  • 渲染配置:开启绘图上下文的抗锯齿、平滑开关,消除绘制边缘锯齿

内容的提问来源于stack exchange,提问作者lily

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:45:03