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

Flutter中如何实现3D对象沿Y轴旋转并调整旋转锚点到对象中心

3D宇航员演示图

实现方案

需要做两处核心修改,分别适配旋转轴切换和锚点校准需求,完整可运行代码如下:

import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_cube/flutter_cube.dart';

class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late Object astronaut;
late final AnimationController _controller;
@override
void initState() {
_controller = AnimationController(
  vsync: this,
  duration: const Duration(seconds: 10),
)..repeat();
astronaut = Object(fileName: 'assets/mercedes/Astronaut.obj');
// 校准模型位置:当前OBJ模型原点在脚部,向上偏移对应距离让模型中心和容器中心重合,数值可根据实际模型大小微调
astronaut.position.y = -4.5;
astronaut.updateTransform();
super.initState();
}

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

@override
Widget build(BuildContext context) {
 return Scaffold(
  backgroundColor: Colors.black,
  appBar: AppBar(
    title: const Text('3D Demo'),
    backgroundColor: Colors.black,
  ),
  body: Center(
    child: AnimatedBuilder(
      animation: _controller,
      builder: (_, child) {
        return Transform.rotate(
          angle: _controller.value * 2 * math.pi,
          // 指定旋转轴为Y轴
          axis: const Offset(0, 1, 0),
          alignment: Alignment.center,
          child: child,
        );
      },
      child: Cube(
        onSceneCreated: (Scene scene) {
          scene.world.add(astronaut);
          scene.camera.zoom = 10;
         },
       ),
     ),
   ),
 );
 }
}

可选优化

如果追求更好的渲染性能,可以直接在3D场景内更新模型的旋转属性,无需使用Flutter上层的Transform组件:

  1. 移除AnimatedBuilder包裹的Transform组件
  2. 在动画监听中直接更新宇航员的Y轴旋转值:
AnimatedBuilder(
  animation: _controller,
  builder: (_, child) {
    astronaut.rotation.y = _controller.value * 360;
    astronaut.updateTransform();
    return child;
  },
  // 其余代码保持不变
)

内容的提问来源于stack exchange,提问作者who-aditya-nawandar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:57:04