JavaFX 3D场景鼠标拖拽旋转相机功能失效 无法调整相机位置
核心问题原因
- 自定义相机未绑定到场景:JavaFX 默认使用内置正交相机渲染,你创建的
PerspectiveCamera仅作为普通节点加入了Group,没有被设置为场景的渲染相机,所以所有对该相机的平移、旋转修改都不会生效。 - 旋转锚点配置错误:你给相机添加的
Rotate变换默认以相机自身位置为旋转中心,而非世界原点,所以即使相机生效,也只会原地旋转,无法实现绕原点轨道运动的效果。 - 坐标对齐问题:场景默认2D原点在左上角,原点位置的坐标轴自然显示在左上角,需要调整对齐让原点对应屏幕中心。
具体修改方案
1. 修改Application启动类
将自定义相机绑定到场景,新增scene.setCamera(g.camera)配置:
public class TestApp extends Application { @Override public void start(Stage stage) throws IOException { RotateCameraExample g = new RotateCameraExample(); Scene scene = new Scene(g, 800, 800, Color.BLACK); // 新增:将自定义相机设置为场景渲染相机 scene.setCamera(g.camera); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(); } }
2. 调整RotateCameraExample配置
- 调整相机初始位置,沿Z轴后移避免和原点重合
- 给旋转变换设置原点为旋转中心
- 调整坐标轴位置对齐屏幕中心
修改后的完整代码如下:
import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.scene.Camera; import javafx.scene.Group; import javafx.scene.PerspectiveCamera; import javafx.scene.paint.Color; import javafx.scene.paint.PhongMaterial; import javafx.scene.shape.Box; import javafx.scene.transform.Rotate; public class RotateCameraExample extends Group { private double anchorX, anchorY; private double anchorAngleX = 0; private double anchorAngleY = 0; private final DoubleProperty angleX = new SimpleDoubleProperty(0); private final DoubleProperty angleY = new SimpleDoubleProperty(0); Camera camera; Group axes; public RotateCameraExample() { axes = buildAxes(); // 新增:将坐标轴原点对齐800x800屏幕中心 axes.setTranslateX(400); axes.setTranslateY(400); getChildren().add(axes); camera = new PerspectiveCamera(true); camera.setFarClip(6000); camera.setNearClip(0.01); camera.setFieldOfView(60); // 调整相机初始位置:与坐标轴同X/Y,沿Z轴后移800单位正对原点 camera.setTranslateX(400); camera.setTranslateY(400); camera.setTranslateZ(800); getChildren().add(camera); initMouseControl(); } private void initMouseControl() { Rotate xRotate = new Rotate(0, Rotate.X_AXIS); Rotate yRotate = new Rotate(0, Rotate.Y_AXIS); // 新增:设置旋转中心为坐标轴原点 xRotate.setPivotX(400); xRotate.setPivotY(400); xRotate.setPivotZ(0); yRotate.setPivotX(400); yRotate.setPivotY(400); yRotate.setPivotZ(0); camera.getTransforms().addAll(xRotate, yRotate); xRotate.angleProperty().bind(angleX); yRotate.angleProperty().bind(angleY); setOnMousePressed(event -> { anchorX = event.getSceneX(); anchorY = event.getSceneY(); anchorAngleX = angleX.get(); anchorAngleY = angleY.get(); }); setOnMouseDragged(event -> { angleX.set(anchorAngleX - (anchorY - event.getSceneY())); angleY.set(anchorAngleY + anchorX - event.getSceneX()); }); } private Group buildAxes() { final Box xAxis = new Box(1200, 10, 10); final Box yAxis = new Box(10, 1200, 10); final Box zAxis = new Box(10, 10, 1200); xAxis.setMaterial(new PhongMaterial(Color.RED)); yAxis.setMaterial(new PhongMaterial(Color.GREEN)); zAxis.setMaterial(new PhongMaterial(Color.BLUE)); Group axisGroup = new Group(); axisGroup.getChildren().addAll(xAxis, yAxis, zAxis); return axisGroup; } }
修改后拖拽鼠标即可实现相机绕坐标轴原点轨道旋转的效果,坐标轴默认显示在屏幕中心。
内容的提问来源于stack exchange,提问作者Joshua Chambers
相关产品推荐
相关产品推荐

