Flutter实现可拖拽纹身图与手臂图叠加并隐藏超出边缘部分
实现方案
以下是基于你提供的代码,实现纹身叠加和拖拽控制的完整解决方案:
修改后的完整代码
class _MyHomePageState extends State<MyHomePage> { Offset imageOffset = Offset(0.0, 0.0); // 纹身初始偏移量 double imageSize = 100.0; // 纹身尺寸(可调整) bool _isDraggable = true; // 控制拖拽与遮罩效果的开关状态 @override Widget build(BuildContext context) { // 提取容器与手臂图的固定尺寸、位置,确保遮罩对齐 final parentWidth = MediaQuery.of(context).size.width * 0.80; final parentHeight = MediaQuery.of(context).size.height * 0.45; final armWidth = MediaQuery.of(context).size.width * .60; final armHeight = MediaQuery.of(context).size.height * .30; final armLeft = (parentWidth - armWidth) / 2; final armTop = (parentHeight - armHeight) / 2; return Scaffold( appBar: AppBar( title: const Text('纹身叠加模拟器'), actions: [ // 拖拽控制开关 Switch( value: _isDraggable, onChanged: (value) => setState(() => _isDraggable = value), activeColor: Colors.orange, ), ], ), body: Center( child: Container( height: parentHeight, width: parentWidth, child: Stack( children: [ // 黑色背景容器 Container( height: parentHeight, width: parentWidth, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(8), ), ), // 固定显示的手臂图片 Positioned( left: armLeft, top: armTop, child: Image.asset( 'assets/Images/arm.png', height: armHeight, width: armWidth, fit: BoxFit.contain, ), ), // 可拖拽/带遮罩的纹身图片 Positioned( left: imageOffset.dx, top: imageOffset.dy, child: GestureDetector( // 仅在开启状态下允许拖拽 onPanUpdate: _isDraggable ? (details) { setState(() { // 更新纹身位置,限制在容器边界内 imageOffset = Offset( (imageOffset.dx + details.delta.dx).clamp( 0.0, parentWidth - imageSize), (imageOffset.dy + details.delta.dy).clamp( 0.0, parentHeight - imageSize), ); }); } : null, child: _isDraggable ? // 开启拖拽时,直接显示完整纹身 Image.asset( 'assets/Images/Tattoo.png', height: imageSize, width: imageSize, color: Colors.orange, fit: BoxFit.cover, ) : // 关闭拖拽时,用手臂图作为遮罩,仅显示重叠区域 ShaderMask( shaderCallback: (bounds) { return ImageShader( AssetImage('assets/Images/arm.png'), TileMode.clamp, TileMode.clamp, // 调整遮罩位置,与手臂图完全对齐 Matrix4.identity() .translate(-armLeft, -armTop) .storage, ); }, // 混合模式:仅保留遮罩不透明区域的纹身内容 blendMode: BlendMode.dstIn, child: Image.asset( 'assets/Images/Tattoo.png', height: imageSize, width: imageSize, color: Colors.orange, fit: BoxFit.cover, ), ), ), ), ], ), ), ), ); } }
关键功能说明
- 拖拽控制开关:AppBar右侧的Switch按钮,切换
_isDraggable状态,控制纹身是否可拖拽。 - 边界限制:拖拽时通过
clamp方法限制纹身位置,确保不会超出黑色容器边界。 - 遮罩效果实现:
- 关闭拖拽时,使用
ShaderMask将手臂图作为遮罩层 - 通过
BlendMode.dstIn混合模式,只显示纹身与手臂图重叠的不透明部分,模拟真实纹身贴附效果 Matrix4.translate调整遮罩位置,确保与界面上显示的手臂图完全对齐,避免错位
- 关闭拖拽时,使用
内容的提问来源于stack exchange,提问作者Hassnain Nisar
相关产品推荐
相关产品推荐

