模块7: 相机与变换系统

2D/3D 变换矩阵、坐标系与相机控制

1. 变换系统概述

每个 DisplayObject 都有一个 Transform 组件,管理本地坐标和世界坐标之间的矩阵变换。

底层使用 gl-matrix 库进行矩阵运算,支持 2D (3x3) 和 3D (4x4) 变换。

2. Transform 组件

// 位移
circle.setPosition(100, 200);       // 设置绝对位置
circle.setPosition(100, 200, 50);  // 3D 位置
circle.translate(10, 20);           // 相对移动
circle.translateLocal(10, 0);       // 本地坐标系移动

// 旋转
circle.setEulerAngles(0, 0, 45);   // 欧拉角 (度)
circle.rotate(0, 0, 30);           // 相对旋转
circle.rotateLocal(0, 0, 15);      // 本地旋转

// 缩放
circle.setLocalScale(2);            // 等比缩放
circle.setLocalScale(2, 1.5);      // 非等比
circle.scaleLocal(1.1, 1.1);       // 相对缩放

// CSS transform 语法也支持
circle.style.transform = 'translate(100px, 50px) rotate(45deg) scale(1.5)';

3. 本地坐标 vs 世界坐标

  世界坐标 (World)               本地坐标 (Local)
  ┌─────────────────┐           ┌─────────────────┐
  │ Canvas (0,0)    │           │ Group 坐标原点    │
  │  ┌─── Group ────│──┐        │  ┌── Circle ──┐  │
  │  │ pos(200,100) │  │        │  │ pos(50,30) │  │
  │  │  ┌─ Circle   │  │        │  │ 相对于 Group │  │
  │  │  │ 世界(250,130) │      │  └────────────┘  │
  │  └──────────────┘  │        └─────────────────┘
  └────────────────────┘

  世界坐标 = 父世界矩阵 × 本地矩阵
// 获取坐标
circle.getPosition();       // 世界坐标 [x, y, z]
circle.getLocalPosition();  // 本地坐标 [x, y, z]

// 获取变换矩阵
circle.getWorldTransform();  // 4x4 世界矩阵
circle.getLocalTransform();  // 4x4 本地矩阵

// 坐标转换
circle.setPosition(worldX, worldY);
const local = circle.getLocalPosition();

4. 相机系统

@antv/g 提供统一的 Camera 类,支持 2D 和 3D 场景:

const camera = canvas.getCamera();

// 2D 场景 - 平移和缩放
camera.pan(100, 50);     // 平移视图
camera.setZoom(1.5);      // 缩放
camera.setZoomByViewportPoint(2, [400, 300]); // 以某点为中心缩放

5. 投影方式

投影适用特点
正交投影 (Orthographic)2D 场景远近物体大小相同
透视投影 (Perspective)3D 场景近大远小,有深度感
// 切换到透视投影(3D 场景)
camera
  .setPosition(300, 200, 500)
  .setFocalPoint(300, 200, 0)
  .setPerspective(0.1, 1000, 50, 1);
// 参数: near, far, fov(度), aspect

// 正交投影(默认)
camera.setOrthographic(width / -2, width / 2, height / 2, height / -2, 0.1, 1000);

6. 相机跟踪模式

模式说明
CameraTrackingMode.DEFAULT固定不动
CameraTrackingMode.ROTATIONAL跟随目标旋转
CameraTrackingMode.TRANSLATIONAL跟随目标平移
CameraTrackingMode.CINEMATIC电影式跟随(有延迟)

7. Landmark 相机书签

// 保存当前相机状态
camera.createLandmark('overview', {
  position: [300, 200, 500],
  focalPoint: [300, 200, 0],
  zoom: 1,
});

camera.createLandmark('detail', {
  position: [100, 100, 200],
  focalPoint: [100, 100, 0],
  zoom: 3,
});

// 平滑过渡到书签位置
camera.gotoLandmark('detail', {
  duration: 1000,
  easing: 'ease-in-out',
});

8. AABB 包围盒

// 每个图形都有轴对齐包围盒
const bounds = circle.getBounds();
bounds.min  // [minX, minY, minZ]
bounds.max  // [maxX, maxY, maxZ]
bounds.getCenter()  // 中心点
bounds.getSize()    // 尺寸

// 本地包围盒(不含父变换)
circle.getLocalBounds();

// 几何包围盒(不含描边/阴影)
circle.getBBox();