1. 插件介绍

vector_math是一个高性能的Dart向量、矩阵和四元数数学库,专为图形和游戏开发设计。该库提供了丰富的几何运算功能,支持2D/3D空间中的向量运算、矩阵变换、四元数旋转等核心操作,是Flutter图形渲染、游戏开发等领域的重要基础库。

在OpenHarmony跨平台开发中,vector_math库经过适配优化,能够完美支持OpenHarmony API 9+版本,为开发者提供高效、精准的数学运算支持。无论是实现3D模型渲染、物理引擎、动画效果还是地理空间计算,vector_math都能提供强大的数学运算能力。

主要功能特性:

  • 支持2D/3D/4D向量运算(Vector2/Vector3/Vector4)
  • 支持2x2/3x3/4x4矩阵变换(Matrix2/Matrix3/Matrix4)
  • 支持四元数旋转(Quaternion)
  • 提供几何实体(AABB、OBB、Plane、Ray、Sphere等)
  • 支持颜色和噪声生成工具
  • 优化的性能和内存使用

2. 环境准备

在开始使用vector_math库之前,需要确保你的开发环境满足以下要求:

  • OpenHarmony SDK API 9+
  • Flutter SDK 3.0+
  • DevEco Studio 4.0+
  • Dart SDK 2.19.6+

3. 包的引入

由于这是一个自定义修改版本的三方库,需要以git形式引入。请按照以下步骤操作:

3.1 配置依赖

在你的Flutter项目的pubspec.yaml文件中添加以下依赖配置:

dependencies:
  flutter:
    sdk: flutter
  vector_math:
    git:
      url: "https://atomgit.com/flutter/packages"
      path: "packages/vector_math/vector_math"

3.2 安装依赖

在项目根目录下运行以下命令安装依赖:

flutter pub get

4. API调用示例

下面通过几个具体的示例来演示vector_math库的核心API使用方法:

4.1 向量运算示例

import 'package:vector_math/vector_math.dart' as v;

void vectorOperations() {
  // 创建向量
  var v1 = v.Vector3(1.0, 2.0, 3.0);
  var v2 = v.Vector3(4.0, 5.0, 6.0);

  // 向量加法
  var sum = v1 + v2;
  print('向量加法: $sum'); // 输出: Vector3(5.0, 7.0, 9.0)

  // 向量点积
  var dotProduct = v1.dot(v2);
  print('向量点积: $dotProduct'); // 输出: 32.0

  // 向量叉积
  var crossProduct = v1.cross(v2);
  print('向量叉积: $crossProduct'); // 输出: Vector3(-3.0, 6.0, -3.0)

  // 向量归一化
  var normalized = v1.normalized();
  print('向量归一化: $normalized'); // 输出: Vector3(0.2672612419124244, 0.5345224838248488, 0.8017837257372732)

  // 向量长度
  var length = v1.length;
  print('向量长度: $length'); // 输出: 3.7416573867739413
}

4.2 矩阵变换示例

import 'package:vector_math/vector_math.dart' as v;

void matrixOperations() {
  // 创建一个向量
  var point = v.Vector3(1.0, 2.0, 3.0);

  // 创建平移矩阵
  var translationMatrix = v.Matrix4.translationValues(10.0, 20.0, 30.0);
  var translatedPoint = translationMatrix.transformed3(point);
  print('平移变换: $translatedPoint'); // 输出: Vector3(11.0, 22.0, 33.0)

  // 创建旋转变换
  var rotationMatrix = v.Matrix4.identity()
    ..rotateX(v.radians(45.0)) // 绕X轴旋转45度
    ..rotateY(v.radians(30.0)) // 绕Y轴旋转30度
    ..rotateZ(v.radians(60.0)); // 绕Z轴旋转60度
  var rotatedPoint = rotationMatrix.transformed3(point);
  print('旋转变换: $rotatedPoint');

  // 创建缩放矩阵
  var scaleMatrix = v.Matrix4.diagonal3Values(2.0, 3.0, 4.0);
  var scaledPoint = scaleMatrix.transformed3(point);
  print('缩放变换: $scaledPoint'); // 输出: Vector3(2.0, 6.0, 12.0)

  // 复合变换 (平移 -> 旋转 -> 缩放)
  var modelMatrix = v.Matrix4.identity()
    ..translate(10.0, 20.0, 30.0)
    ..rotateY(v.radians(45.0))
    ..scale(2.0, 2.0, 2.0);
  var transformedPoint = modelMatrix.transformed3(point);
  print('复合变换: $transformedPoint');
}

4.3 四元数旋转示例

import 'package:vector_math/vector_math.dart' as v;

void quaternionOperations() {
  // 创建一个向量
  var point = v.Vector3(0.0, 0.0, 1.0);

  // 创建四元数 (绕Y轴旋转90度)
  var quaternion = v.Quaternion.axisAngle(v.Vector3(0.0, 1.0, 0.0), v.radians(90.0));

  // 应用四元数旋转
  var rotatedPoint = point.clone()..applyQuaternion(quaternion);
  print('四元数旋转: $rotatedPoint'); // 输出: Vector3(1.0, 0.0, 0.0)

  // 四元数插值 (SLERP)
  var q1 = v.Quaternion.axisAngle(v.Vector3(0.0, 1.0, 0.0), v.radians(0.0));
  var q2 = v.Quaternion.axisAngle(v.Vector3(0.0, 1.0, 0.0), v.radians(180.0));
  var qSlerp = v.Quaternion.slerp(q1, q2, 0.5);
  print('四元数插值: $qSlerp');
}

4.4 3D立方体旋转交互示例

下面是一个完整的Flutter页面示例,展示如何使用vector_math库实现一个可交互的3D旋转立方体:

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as v;

class CubeRotationPage extends StatefulWidget {
  const CubeRotationPage({Key? key}) : super(key: key);

  
  State<CubeRotationPage> createState() => _CubeRotationPageState();
}

class _CubeRotationPageState extends State<CubeRotationPage> {
  double x = 0.0;
  double y = 0.0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('3D立方体旋转示例'),
      ),
      body: Center(
        child: GestureDetector(
          onPanUpdate: (details) {
            setState(() {
              y -= details.delta.dx / 100;
              x += details.delta.dy / 100;
            });
          },
          child: Transform(
            transform: Matrix4.identity()
              ..setEntry(3, 2, 0.001) // 透视效果
              ..rotateX(x)
              ..rotateY(y),
            alignment: FractionalOffset.center,
            child: SizedBox(
              width: 200,
              height: 200,
              child: Stack(
                children: [
                  // 前面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Container(
                      width: 200,
                      height: 200,
                      color: Colors.red.withOpacity(0.7),
                      child: const Center(child: Text('前')),
                    ),
                  ),
                  // 后面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Transform(
                      transform: Matrix4.identity()..translate(0.0, 0.0, -200.0),
                      alignment: FractionalOffset.center,
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.blue.withOpacity(0.7),
                        child: const Center(child: Text('后')),
                      ),
                    ),
                  ),
                  // 左面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Transform(
                      transform: Matrix4.identity()..rotateY(v.radians(90))..translate(100.0, 0.0, 100.0),
                      alignment: FractionalOffset.centerLeft,
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.green.withOpacity(0.7),
                        child: const Center(child: Text('左')),
                      ),
                    ),
                  ),
                  // 右面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Transform(
                      transform: Matrix4.identity()..rotateY(v.radians(-90))..translate(-100.0, 0.0, 100.0),
                      alignment: FractionalOffset.centerRight,
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.yellow.withOpacity(0.7),
                        child: const Center(child: Text('右')),
                      ),
                    ),
                  ),
                  // 上面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Transform(
                      transform: Matrix4.identity()..rotateX(v.radians(-90))..translate(0.0, 100.0, 100.0),
                      alignment: FractionalOffset.topCenter,
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.purple.withOpacity(0.7),
                        child: const Center(child: Text('上')),
                      ),
                    ),
                  ),
                  // 下面
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: Transform(
                      transform: Matrix4.identity()..rotateX(v.radians(90))..translate(0.0, -100.0, 100.0),
                      alignment: FractionalOffset.bottomCenter,
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.orange.withOpacity(0.7),
                        child: const Center(child: Text('下')),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

5. 常见使用场景

5.1 图形渲染

在Flutter自定义绘制中,vector_math可用于计算点、线、面的位置和变换,实现复杂的图形渲染效果。

class MyPainter extends CustomPainter {
  
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..color = Colors.blue;

    // 使用向量定义多边形顶点
    var points = [
      v.Vector2(100, 100),
      v.Vector2(200, 50),
      v.Vector2(300, 150),
      v.Vector2(250, 250),
      v.Vector2(150, 200),
    ];

    // 将向量转换为Offset并绘制多边形
    var offsets = points.map((p) => Offset(p.x, p.y)).toList();
    canvas.drawPolygon(offsets, true, paint);

    // 应用矩阵变换
    var matrix = v.Matrix4.translationValues(0, 50, 0)..scale(1.2);
    var transformedPoints = points.map((p) {
      var v3 = matrix.transformed3(v.Vector3(p.x, p.y, 0));
      return Offset(v3.x, v3.y);
    }).toList();

    paint.color = Colors.red;
    canvas.drawPolygon(transformedPoints, true, paint);
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

5.2 动画效果

利用vector_math可以实现平滑的动画过渡效果,特别是在3D空间中的变换动画。

class AnimatedCube extends StatefulWidget {
  const AnimatedCube({Key? key}) : super(key: key);

  
  State<AnimatedCube> createState() => _AnimatedCubeState();
}

class _AnimatedCubeState extends State<AnimatedCube> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _rotationX;
  late Animation<double> _rotationY;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 10),
      vsync: this,
    )..repeat();

    _rotationX = Tween<double>(begin: 0, end: 2 * math.pi).animate(
      CurvedAnimation(parent: _controller, curve: Curves.linear),
    );
    _rotationY = Tween<double>(begin: 0, end: 2 * math.pi).animate(
      CurvedAnimation(parent: _controller, curve: Curves.linear),
    );
  }

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Transform(
          transform: Matrix4.identity()
            ..rotateX(_rotationX.value)
            ..rotateY(_rotationY.value),
          alignment: FractionalOffset.center,
          child: Container(
            width: 150,
            height: 150,
            color: Colors.green,
          ),
        );
      },
    );
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

6. 性能优化建议

  1. 重用对象:避免频繁创建向量和矩阵对象,尽量重用已有的对象

    // 不好的做法
    for (int i = 0; i < 1000; i++) {
      var v = Vector3(i.toDouble(), 0, 0);
      // 使用v...
    }
    
    // 好的做法
    var v = Vector3.zero();
    for (int i = 0; i < 1000; i++) {
      v.setValues(i.toDouble(), 0, 0);
      // 使用v...
    }
    
  2. 使用批量操作:优先使用批量操作方法,减少函数调用开销

    // 不好的做法
    for (int i = 0; i < points.length; i++) {
      points[i] = matrix.transformed3(points[i]);
    }
    
    // 好的做法(如果库支持)
    matrix.transform3List(points);
    
  3. 避免不必要的计算:只在需要时进行复杂的数学运算

  4. 使用Float32List存储:对于大量向量数据,使用Float32List存储可以提高内存效率

7. 总结

vector_math库是Flutter开发中不可或缺的数学运算工具库,特别在图形渲染、游戏开发、动画效果等领域具有广泛的应用。通过本文的介绍,我们了解了vector_math库的核心功能、安装配置方法以及实际使用示例。

在OpenHarmony跨平台开发中,vector_math库经过适配优化,能够提供高效、稳定的数学运算支持,为开发者实现复杂的图形效果和交互体验提供了坚实的基础。

无论是实现简单的2D向量运算,还是复杂的3D场景渲染,vector_math都能提供强大的功能支持。通过合理使用vector_math库,开发者可以大幅提高开发效率,实现更加精美的视觉效果和流畅的交互体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐