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
相关产品推荐
相关产品推荐

