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

Flutter如何实现阴影随对象同步旋转 解决容器旋转宽度丢失问题

问题原因

你遇到的“宽度丢失”是两个原因共同导致的:

  • Flutter的Transform仅在绘制阶段对组件做变换,不会修改组件实际布局尺寸。你当前旋转的是无厚度的2D平面Container,当它绕Y轴旋转到与屏幕垂直的角度时,平面的投影宽度为0,视觉上就像消失了。
  • 你代码中的AnimatedContainer没有设置背景色,仅携带boxShadow属性,本身是完全透明的。当平面旋转到与屏幕接近垂直的角度时,平面阴影会完全落在自身方向或背离屏幕方向,自然无法被观察到。

解决方案

我们可以通过模拟3D厚度、固定主体绘制基础、同步阴影变换来解决这个问题,修改后的代码如下:

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

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

  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> with TickerProviderStateMixin {
  late final AnimationController _controller;
  @override
  void initState() {
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 25),
    )..repeat();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    double screenHeight = MediaQuery.of(context).size.height;
    double screenWidth = MediaQuery.of(context).size.width;
    // 定义主体厚度,可自行调整
    const double thickness = 8;

    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        title: const Text('3D Demo'),
        backgroundColor: Colors.black,
      ),
      body: Center(
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [Colors.black, Colors.black],
            ),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Divider(),
              const Divider(),
              SizedBox(
                height: screenHeight * 0.5,
                child: Stack(
                  children: [
                    Center(
                      child: AnimatedBuilder(
                        animation: _controller,
                        builder: (_, child) {
                          double rotateY = _controller.value * (-math.pi);
                          return Transform(
                            alignment: Alignment.center,
                            transform: Matrix4.identity()
                              ..setEntry(3, 2, 0.001)
                              ..rotateY(rotateY),
                            child: child,
                          );
                        },
                        // 用Stack堆叠正面、厚度面、阴影层,模拟3D效果
                        child: Stack(
                          alignment: Alignment.center,
                          children: [
                            // 正面主体
                            Container(
                              height: 100,
                              width: screenWidth * 0.8,
                              decoration: BoxDecoration(
                                color: Colors.white, // 给主体加背景色,保证可见
                                borderRadius: BorderRadius.circular(100),
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.yellow.withOpacity(0.6),
                                    spreadRadius: 1,
                                    blurRadius: 16,
                                    offset: const Offset(0, 0),
                                  ),
                                ],
                              ),
                            ),
                            // 模拟厚度的侧面,旋转到90度时显示
                            Transform(
                              alignment: Alignment.centerRight,
                              transform: Matrix4.identity()..rotateY(math.pi/2),
                              child: Container(
                                height: 100,
                                width: thickness,
                                decoration: BoxDecoration(
                                  color: Colors.grey[800],
                                  borderRadius: BorderRadius.circular(4),
                                ),
                              ),
                            )
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

优化说明

  • 给正面Container添加了明确的背景色和固定宽度,避免透明导致的视觉消失
  • 新增了厚度侧面,旋转到与屏幕垂直的角度时会显示厚度,不会完全丢失宽度
  • 阴影直接绑定在正面Container上,会跟随整个3D变换同步旋转,始终和主体位置匹配
  • 你可以根据需求调整厚度值、阴影参数、主体宽度,实现想要的视觉效果

内容的提问来源于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 04:39:01