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

JavaFX修改旋转支点后矩形跳动问题求助

解决JavaFX矩形拖动旋转支点后跳动问题

问题描述

我需要拖动矩形的旋转支点来进行旋转操作,目前已实现矩形围绕新支点旋转,但矩形会出现跳动现象。推测需要对矩形进行平移处理,但不知道具体如何操作,希望矩形在更换支点后能保持原有位置,以便进行后续旋转操作。

问题原因

当旋转支点(pivot)改变时,Rotate变换的基准点发生了变化,而矩形当前的视觉位置是基于旧支点旋转后的结果,直接切换新支点会导致旋转基准偏移,从而出现跳动。需要计算支点移动的偏移量,并将其转换为矩形的平移量,抵消位置变化。

解决方案

在拖动支点释放后,通过以下步骤调整矩形位置:

  1. 计算旧支点到新支点的偏移量
  2. 根据当前旋转角度,将偏移量转换为矩形局部坐标系下的平移量
  3. 应用平移量到矩形,保持视觉位置不变

修改后的完整代码

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

import java.io.IOException;

public class T5_4_Rotar_PivotXY_2 extends Application {

    double anguloFinal = 0;
    double pivoteX = 250; // initial rotate pivotX
    double pivoteY = 150; // initial rotate pivotY

    @Override
    public void start(Stage stage) throws IOException {

        Pane pane = new Pane();
        Scene scene = new Scene(pane,500,500);

        double x0 = 50;
        double y0 = 50;
        double ancho = 200; // width
        double alto = 100; // height
        Rectangle r = new Rectangle(x0, y0, ancho, alto);
        r.setFill(Color.YELLOW);

        // pivot simbol
        Circle circle1 = new Circle(pivoteX,pivoteY,4);
        circle1.setFill(Color.TRANSPARENT);
        circle1.setStroke(Color.BLACK);
        Line line1 = new Line(pivoteX-6,pivoteY,pivoteX+6,pivoteY);
        Line line2 = new Line(pivoteX,pivoteY-6,pivoteX,pivoteY+6);
        Group centro = new Group(circle1,line1,line2);

        pane.getChildren().addAll(r,centro);

        Rotate rotacion = new Rotate();
        rotacion.setPivotX(pivoteX);
        rotacion.setPivotY(pivoteY);

        r.getTransforms().add(rotacion);


        // Rotation event
        pane.setOnMousePressed(e1 -> {

            pane.setOnMouseDragged(e2 -> {

                double anguloPressed = Math.toDegrees(Math.atan2((e1.getSceneY() - pivoteY),(e1.getSceneX() - pivoteX))); 
                double anguloDragged = Math.toDegrees(Math.atan2((e2.getSceneY() - pivoteY),(e2.getSceneX() - pivoteX))); 
                double angulo = anguloDragged - anguloPressed + anguloFinal;

                rotacion.setAngle(angulo);

                pane.setOnMouseReleased(e3 -> {
                    anguloFinal = angulo;
                });
            });
        });

        // Dragging the pivot
        centro.setOnMousePressed(e1 -> {

            centro.setOnMouseDragged(e2 -> {
                centro.setTranslateX(e2.getSceneX() - e1.getSceneX());
                centro.setTranslateY(e2.getSceneY() - e1.getSceneY());
                e2.consume();

                centro.setOnMouseReleased(e3 -> {
                    centro.setLayoutX(centro.getLayoutX() + centro.getTranslateX());
                    centro.setLayoutY(centro.getLayoutY() + centro.getTranslateY());
                    centro.setTranslateX(0);
                    centro.setTranslateY(0);

                    // 记录旧支点位置
                    double oldPivotX = pivoteX;
                    double oldPivotY = pivoteY;

                    // 新支点
                    pivoteX = centro.getLayoutX() + 250;
                    pivoteY = centro.getLayoutY() + 150;

                    // 计算支点偏移量
                    double dx = pivoteX - oldPivotX;
                    double dy = pivoteY - oldPivotY;

                    // 当前旋转角度(弧度)
                    double angleRad = Math.toRadians(rotacion.getAngle());

                    // 将偏移量旋转转换为矩形局部平移量,抵消支点变化影响
                    double translateX = dx * Math.cos(angleRad) + dy * Math.sin(angleRad);
                    double translateY = -dx * Math.sin(angleRad) + dy * Math.cos(angleRad);

                    // 应用平移保持矩形位置不变
                    r.setTranslateX(r.getTranslateX() + translateX);
                    r.setTranslateY(r.getTranslateY() + translateY);

                    // 更新旋转支点
                    rotacion.setPivotX(pivoteX);
                    rotacion.setPivotY(pivoteY);

                });
            });
        });

        stage.setTitle("T5 4 Rotate PivotXY 2");
        stage.setScene(scene);
        stage.show();
    }

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

关键代码说明

  • 记录旧支点位置,计算新支点与旧支点的偏移量dx、dy
  • 将旋转角度转换为弧度,使用旋转矩阵计算矩形需要的平移量(适配当前旋转状态)
  • 更新矩形的translateX和translateY,抵消支点变化带来的位置偏移
  • 最后更新旋转变换的支点参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:13:21