Flutter三维曲线绘制插件three_js_curves的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter三维曲线绘制插件three_js_curves的使用

Pub Version 分析 许可证: MIT

three_js_curves 是一个用于在项目中创建和操作曲线几何图形的三js API。

此插件是 three.jsthree_dart 的 Dart 转换版本,最初由 @mrdoob 创建,并由 @wasabia 提供了 Dart 版本的转换。

使用

此API允许用户为三js创建曲线模型。

贡献

欢迎贡献。 如果遇到任何问题,请查看 现有问题。如果没有找到相关问题,请打开一个新问题。 对于非简单修复,请在提交拉取请求前先创建一个新问题。 对于简单修复,可以直接提交拉取请求。


示例代码

import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:three_js_core/three_js_core.dart' as three;
import 'package:three_js_text/three_js_text.dart';
import 'package:three_js_math/three_js_math.dart' as tmath;
import 'package:three_js_curves/three_js_curves.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // 此小部件是您的应用程序的根。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const WebglGeometryExtrudeShapes(),
    );
  }
}

class WebglGeometryExtrudeShapes extends StatefulWidget {
  const WebglGeometryExtrudeShapes({super.key});

  [@override](/user/override)
  createState() => _State();
}

class _State extends State<WebglGeometryExtrudeShapes> {
  late three.ThreeJS threeJs;

  [@override](/user/override)
  void initState() {
    threeJs = three.ThreeJS(
      onSetupComplete: (){setState(() {});},
      setup: setup,
    );
    super.initState();
  }

  [@override](/user/override)
  void dispose() {
    threeJs.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return threeJs.build();
  }

  Future<void> setup() async {
    threeJs.scene = three.Scene();
    threeJs.scene.background = tmath.Color.fromHex32(0x222222);

    threeJs.camera = three.PerspectiveCamera(45, threeJs.width / threeJs.height, 1, 1000);
    threeJs.camera.position.setValues(0, 0, 500);

    threeJs.scene.add(three.AmbientLight(0x666666));

    final light = three.PointLight(0xffffff, 0.9, 0, 0);
    light.position.setFrom(threeJs.camera.position);
    threeJs.scene.add(light);

    final closedSpline = CatmullRomCurve3(
      points: [
        tmath.Vector3(-60, -100, 60),
        tmath.Vector3(-60, 20, 60),
        tmath.Vector3(-60, 120, 60),
        tmath.Vector3(60, 20, -60),
        tmath.Vector3(60, -100, -60)
      ]
    );

    closedSpline.curveType = 'catmullrom';
    closedSpline.closed = true;

    final ExtrudeGeometryOptions extrudeSettings1 = ExtrudeGeometryOptions(
      steps: 100,
      bevelEnabled: false,
      extrudePath: closedSpline
    );

    final List<tmath.Vector2> pts1 = [];
    const count = 3;

    for (int i = 0; i < count; i++) {
      const l = 20;
      final a = 2 * i / count * math.pi;
      pts1.add(tmath.Vector2(math.cos(a) * l, math.sin(a) * l));
    }

    final shape1 = Shape(pts1);
    final geometry1 = ExtrudeGeometry([shape1], extrudeSettings1);
    final material1 = three.MeshLambertMaterial.fromMap({'color': 0xb00000, 'wireframe': false});
    final mesh1 = three.Mesh(geometry1, material1);

    mesh1.castShadow = true;
    mesh1.receiveShadow = true;
    threeJs.scene.add(mesh1);

    final List<tmath.Vector3> randomPoints = [];

    for (int i = 0; i < 10; i++) {
      randomPoints.add(
        tmath.Vector3((i - 4.5) * 50, -50 + math.Random().nextDouble() * (50 - -50), -50 + math.Random().nextDouble() * (50 - -50))
      );
    }

    final randomSpline = CatmullRomCurve3(points: randomPoints);

    final ExtrudeGeometryOptions extrudeSettings2 = ExtrudeGeometryOptions(
      steps: 200,
      bevelEnabled: false,
      extrudePath: randomSpline
    );

    final List<tmath.Vector2> pts2 = [];
    const numPts = 5;

    for (int i = 0; i < numPts * 2; i++) {
      final l = i % 2 == 1 ? 10 : 20;
      final a = i / numPts * math.pi;
      pts2.add(tmath.Vector2(math.cos(a) * l, math.sin(a) * l));
    }

    final shape2 = Shape(pts2);
    final geometry2 = ExtrudeGeometry([shape2], extrudeSettings2);
    final material2 = three.MeshLambertMaterial.fromMap({'color': 0xff8000, 'wireframe': false});
    final mesh2 = three.Mesh(geometry2, material2);

    threeJs.scene.add(mesh2);

    final materials = three.GroupMaterial([material1, material2]);

    final ExtrudeGeometryOptions extrudeSettings3 = ExtrudeGeometryOptions(
      depth: 20,
      steps: 1,
      bevelEnabled: true,
      bevelThickness: 2,
      bevelSize: 4,
      bevelSegments: 1
    );

    final geometry3 = ExtrudeGeometry([shape2], extrudeSettings3);
    final mesh3 = three.Mesh(geometry3, materials);
    mesh3.position.setValues(50, 100, 50);
    threeJs.scene.add(mesh3);
  }
}

更多关于Flutter三维曲线绘制插件three_js_curves的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter三维曲线绘制插件three_js_curves的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,我可以为你提供一个关于如何使用 three_js_curves 插件在 Flutter 中绘制三维曲线的示例代码。three_js_curves 是一个 Flutter 插件,它允许你使用 Three.js 在 Flutter 应用中绘制三维图形。请注意,由于 Flutter 本身是基于 Dart 的,而 Three.js 是基于 JavaScript 的,因此这个插件通常是通过 WebView 或其他方式将 Three.js 集成到 Flutter 应用中的。

以下是一个简化的示例,展示了如何在 Flutter 中使用 three_js_curves 插件绘制一个简单的三维曲线。这个示例假设你已经安装并配置好了 three_js_curves 插件。

首先,确保你的 pubspec.yaml 文件中已经添加了 three_js_curves 依赖:

dependencies:
  flutter:
    sdk: flutter
  three_js_curves: ^最新版本号  # 请替换为实际的最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,在你的 Flutter 应用中,你可以创建一个页面来展示三维曲线。以下是一个简单的示例代码:

import 'package:flutter/material.dart';
import 'package:three_js_curves/three_js_curves.dart';
import 'dart:html' as html;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Three.js Curves in Flutter'),
        ),
        body: Center(
          child: WebViewExample(),
        ),
      ),
    );
  }
}

class WebViewExample extends StatefulWidget {
  @override
  _WebViewExampleState createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  late WebViewController _controller;

  @override
  Widget build(BuildContext context) {
    return WebView(
      initialUrl: Uri.dataFromString(
        _createThreeJsContent(),
        mimeType: 'text/html',
        encoding: html.Encoding.getByName('utf-8')
      ).toString(),
      javascriptMode: JavascriptMode.unrestricted,
      onWebViewCreated: (WebViewController webViewController) {
        _controller = webViewController;
      },
    );
  }

  String _createThreeJsContent() {
    return '''
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Three.js Curve</title>
        <style>
          body { margin: 0; }
          canvas { display: block; }
        </style>
      </head>
      <body>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
        <script>
          // Basic setup
          var scene = new THREE.Scene();
          var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
          var renderer = new THREE.WebGLRenderer();
          renderer.setSize(window.innerWidth, window.innerHeight);
          document.body.appendChild(renderer.domElement);

          // Create a curve
          var curve = new THREE.CatmullRomCurve3([
            new THREE.Vector3(-10, 0, 10),
            new THREE.Vector3(-5, 5, 5),
            new THREE.Vector3(0, 0, 0),
            new THREE.Vector3(5, -5, 5),
            new THREE.Vector3(10, 0, 10)
          ]);

          var points = curve.getPoints(50);
          var geometry = new THREE.BufferGeometry().setFromPoints(points);
          var material = new THREE.LineBasicMaterial({ color: 0xff0000 });
          var line = new THREE.Line(geometry, material);
          scene.add(line);

          camera.position.z = 50;

          // Render loop
          function animate() {
            requestAnimationFrame(animate);

            // Rotate the curve for demo purposes
            curve.points[1].x += 0.01;
            curve.points[2].y += 0.01;

            // Regenerate points and update geometry
            var newPoints = curve.getPoints(50);
            geometry.attributes.position.needsUpdate = true;
            geometry.setFromPoints(newPoints);

            renderer.render(scene, camera);
          }
          animate();
        </script>
      </body>
      </html>
    ''';
  }
}

在这个示例中,我们使用了 webview_flutter 插件来嵌入一个 WebView,并在其中加载了一个包含 Three.js 代码的 HTML 字符串。这个 HTML 字符串创建了一个简单的 Three.js 场景,并在其中绘制了一个 CatmullRom 曲线。

请注意,由于 Flutter 和 WebView 的限制,这种方法可能不是性能最优的,特别是对于复杂的三维图形。对于更复杂的应用,你可能需要考虑使用更底层的图形库,如 Flutter 的 sceneform 或直接使用原生开发平台(如 Android 或 iOS)上的 Three.js 集成。

另外,这个示例代码假设你已经有了 webview_flutter 插件的依赖,如果没有,你需要在 pubspec.yaml 文件中添加它:

dependencies:
  webview_flutter: ^最新版本号  # 请替换为实际的最新版本号

并运行 flutter pub get 来获取依赖。然后,确保你的 Flutter 环境已经正确配置了 WebView 支持(对于 Android,可能需要配置一些额外的权限和设置)。

希望这个示例能帮助你在 Flutter 应用中使用 three_js_curves 插件绘制三维曲线!

回到顶部