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

Java Swing中实现随鼠标与中心距离衰减的动点运动控制问题

带边界限制的动点趋近实现
  • 全程固定面板几何中心作为唯一参照点,不做任何位置偏移,中心坐标取固定值getWidth() / 2、getHeight() / 2。
  • 提前设定动点的最大允许偏移半径(比如150像素),无论鼠标离中心多远,动点最多只能从中心向外移动这个距离,从根源上避免无限制外移。
  • 你之前用Math.hypot(width / 2 - mouseX , height / 2 - mouseY)计算鼠标到中心距离的逻辑是正确的,之前没实现预期效果的原因是计算出距离后没有参与动点坐标的推导,依然直接使用鼠标的绝对坐标作为动点位置,才会出现动点和鼠标完全重合、无边界移动的问题。
  • 坐标推导规则:
    • 当鼠标离中心的实际距离小于等于最大允许偏移半径时,动点沿着中心与鼠标的连线方向,保持和鼠标相同的离中心距离,此时动点和鼠标视觉上重合,和原有效果一致。
    • 当鼠标离中心的实际距离超过最大允许偏移半径时,动点的偏移量固定为最大半径值,不再跟随鼠标向外移动。此时鼠标离中心越远,和动点的视觉间隔越大,对应“距离越大、运动驱动力越小、阈值达到后无法支撑动点继续外移”的预期效果。

修正后的完整代码

import javax.swing.*;
import java.awt.*;

public class Example extends JPanel {
    private static final int size = 500;
    // 动点最大允许离中心的偏移半径,可根据需求调整数值
    private static final int MAX_OFFSET = 150;

    public Example() {
        this.setPreferredSize(new Dimension(size, size));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        // 固定绘制作为参照点的屏幕中心
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        g2d.fillOval(centerX - 3, centerY - 3, 6, 6);

        // 获取鼠标相对于当前面板的坐标
        Point mousePoint = MouseInfo.getPointerInfo().getLocation();
        SwingUtilities.convertPointFromScreen(mousePoint, this);

        // 计算鼠标相对于中心的方向分量、直线距离
        int dx = mousePoint.x - centerX;
        int dy = mousePoint.y - centerY;
        double mouseDistToCenter = Math.hypot(dx, dy);

        // 计算动点实际绘制坐标
        int dotX, dotY;
        if (mouseDistToCenter == 0) {
            // 鼠标恰好落在中心时,动点直接放在中心位置,避免除以0的计算错误
            dotX = centerX;
            dotY = centerY;
        } else {
            // 实际允许的偏移量:取鼠标实际距离和最大偏移半径的较小值
            double actualOffset = Math.min(mouseDistToCenter, MAX_OFFSET);
            // 按方向比例归一化后计算动点最终坐标
            dotX = (int) (centerX + (dx / mouseDistToCenter) * actualOffset);
            dotY = (int) (centerY + (dy / mouseDistToCenter) * actualOffset);
        }

        // 绘制动点
        g2d.fillOval(dotX - 5, dotY - 5, 10, 10);
        repaint();
    }

    private static void createFrame() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new Example());
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(Example::createFrame);
    }
}

效果调整方式

  • 直接修改MAX_OFFSET的数值即可改变触发外移停止的阈值:数值越小,动点能达到的最大外移距离越近,驱动力衰减触发越早;数值越大,动点可以跟随鼠标移动更远的距离才会触发边界限制。
  • 整个计算过程不需要复杂的向量物理知识,本质是把“从中心到鼠标的连线”按比例缩放到实际允许的长度上,落点就是动点的最终位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 20:45:03