Flutter页面转场中如何使用SVG作为ShaderMask着色器实现转场动画
基于SVG实现ShaderMask页面转场动画相关问题
现有径向渐变实现代码
当前页面转场通过ShaderMask实现径向渐变扩散动画,代码如下:
transitionsBuilder: (context, animation, secondaryAnimation, child) => TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: Duration(milliseconds: 1000), curve: Curves.easeIn, child: child, builder: (BuildContext context, double value, Widget? child) { return ShaderMask( child: child, shaderCallback: (rect) { return RadialGradient( colors: [Colors.white, Colors.white, Colors.transparent, Colors.transparent], stops: [0.0, 0.25, 0.6, 1.0], center: FractionalOffset(.5, .5), radius: value * 5, ).createShader(rect); } ); }, )
目标效果
需要替换上述径向渐变为基于SVG生成的着色器,效果逻辑保持一致:SVG整体逐步放大,直到内部白色圆形填满整个页面,呈现蓝色圆环向外扩张的转场效果。示例两色SVG代码如下:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="600" viewBox="-300 -300 600 600"> <circle r="100" fill="blue" /> <circle r="50" fill="white" /> </svg>
已尝试的实现方案
已尝试通过ImageShader()实现该效果,编写了将SVG转换为ImageInfo对象的异步方法,代码如下:
Future<void> getImageShader(int width, int height) async { final completer = Completer<ImageInfo>(); ResizeImage(***my svg provider object ***, width: width, height: height) .resolve(ImageConfiguration(size: Size(width.toDouble(), height.toDouble()))) .addListener(ImageStreamListener((info, _) => completer.complete(info))); final info = await completer.future; return ImageShader( info.image, TileMode.clamp, TileMode.clamp, Float64List.fromList(Matrix4.identity().storage), ); }
当前遇到的卡点
getImageShader是异步方法,但transitionsBuilder的每一帧渲染都需要同步获取着色器,无法在ShaderMask的shaderCallback回调函数中直接调用该异步方法。
补充说明
- 上述提供的SVG仅为简化示例,实际业务中使用的SVG结构可能更复杂
- 该功能面向桌面端应用开发
内容的提问来源于stack exchange,提问作者alex smith
相关产品推荐
相关产品推荐

