Flutter 框架跨平台鸿蒙开发 - 阴影生成器应用
运行效果图阴影生成器是一款面向UI设计师和前端开发者的实用工具应用。通过直观的可视化界面,用户可以实时调整阴影的各项参数,即时预览效果,并一键生成CSS或Flutter代码。无论是柔和的卡片阴影、炫酷的霓虹效果,还是多层叠加的高级阴影,都能轻松创建。应用内置10种精心设计的预设效果,涵盖从基础到高级的各种阴影样式。颜色选择器支持HSL色彩模式,让颜色调整更加精准。生成的代码可直接复制使用,大幅提升
阴影生成器应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
阴影生成器是一款面向UI设计师和前端开发者的实用工具应用。通过直观的可视化界面,用户可以实时调整阴影的各项参数,即时预览效果,并一键生成CSS或Flutter代码。无论是柔和的卡片阴影、炫酷的霓虹效果,还是多层叠加的高级阴影,都能轻松创建。
应用内置10种精心设计的预设效果,涵盖从基础到高级的各种阴影样式。颜色选择器支持HSL色彩模式,让颜色调整更加精准。生成的代码可直接复制使用,大幅提升开发效率。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 实时预览 | 阴影效果即时显示 | Container + BoxShadow |
| 参数调节 | 偏移、模糊、扩散等 | Slider组件 |
| 颜色选择 | HSL色彩模式选择 | 自定义颜色对话框 |
| 预设效果 | 10种常用阴影样式 | ShadowPreset模型 |
| 代码生成 | CSS/Flutter代码输出 | 字符串模板 |
| 一键复制 | 复制代码到剪贴板 | Clipboard API |
1.3 阴影参数说明
| 参数 | 说明 | 范围 | 默认值 |
|---|---|---|---|
| 水平偏移(X) | 阴影水平方向偏移量 | -100~100px | 0 |
| 垂直偏移(Y) | 阴影垂直方向偏移量 | -100~100px | 4 |
| 模糊半径 | 阴影模糊程度 | 0~100px | 8 |
| 扩散半径 | 阴影扩散范围 | -50~50px | 0 |
| 透明度 | 阴影颜色透明度 | 0~1 | 0.25 |
| 内阴影 | 阴影在盒子内部 | true/false | false |
1.4 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 目标平台 | 鸿蒙OS | API 21+ |
1.5 项目结构
lib/
└── main_shadow_generator.dart
├── ShadowGeneratorApp # 应用入口
├── ShadowPreset # 预设效果模型
├── ShadowGeneratorPage # 主页面
│ ├── _buildPreviewSection() # 预览区域
│ ├── _buildPresetsSection() # 预设效果区
│ ├── _buildControlsSection() # 参数控制区
│ └── _buildCodeSection() # 代码生成区
└── _ColorPickerDialog # 颜色选择对话框
├── _buildHueSlider() # 色相滑块
├── _buildSaturationSlider() # 饱和度滑块
├── _buildLightnessSlider() # 亮度滑块
└── _buildAlphaSlider() # 透明度滑块
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 数据流程图
2.4 阴影生成流程
三、核心模块设计
3.1 数据模型设计
3.1.1 预设效果模型 (ShadowPreset)
class ShadowPreset {
final String name; // 预设名称
final List<BoxShadow> shadows; // 阴影列表(支持多层)
final String code; // CSS代码示例
}
3.1.2 预设效果分布
3.1.3 阴影参数状态
class _ShadowGeneratorPageState extends State<ShadowGeneratorPage> {
// 阴影参数
double _offsetX = 0; // 水平偏移
double _offsetY = 4; // 垂直偏移
double _blurRadius = 8; // 模糊半径
double _spreadRadius = 0; // 扩散半径
Color _shadowColor = Colors.black; // 阴影颜色
double _shadowOpacity = 0.25; // 阴影透明度
bool _isInset = false; // 是否内阴影
// 盒子参数
Color _boxColor = Colors.white; // 盒子颜色
double _boxWidth = 200; // 盒子宽度
double _boxHeight = 200; // 盒子高度
double _borderRadius = 16; // 圆角半径
Color _backgroundColor = Color(0xFFF5F5F5); // 背景颜色
}
3.2 代码生成算法
3.2.1 CSS代码生成
3.2.2 Flutter代码生成
3.2.3 代码生成核心实现
String get _cssCode {
final inset = _isInset ? 'inset ' : '';
final r = _shadowColor.r.toInt();
final g = _shadowColor.g.toInt();
final b = _shadowColor.b.toInt();
final a = _shadowOpacity.toStringAsFixed(2);
return 'box-shadow: $inset${_offsetX.toInt()}px '
'${_offsetY.toInt()}px ${_blurRadius.toInt()}px '
'${_spreadRadius.toInt()}px rgba($r, $g, $b, $a);';
}
String get _flutterCode {
final inset = _isInset ? 'inset: true,\n ' : '';
final r = _shadowColor.r.toInt();
final g = _shadowColor.g.toInt();
final b = _shadowColor.b.toInt();
return '''BoxShadow(
color: Color.fromRGBO($r, $g, $b, ${_shadowOpacity.toStringAsFixed(2)}),
blurRadius: ${_blurRadius.toStringAsFixed(1)},
spreadRadius: ${_spreadRadius.toStringAsFixed(1)},
offset: Offset(${_offsetX.toStringAsFixed(1)}, ${_offsetY.toStringAsFixed(1)}),
$inset)''';
}
3.3 颜色选择器设计
3.3.1 HSL色彩模式
3.3.2 颜色转换流程
3.4 页面结构设计
3.4.1 界面布局
3.4.2 控制面板布局
┌─────────────────────────────────────────────────────────────┐
│ 阴影参数 │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 水平偏移(X) ═══════════════════════════════○═══ 0.0 │ │
│ │ 垂直偏移(Y) ═══════════════════════════○═══════ 4.0 │ │
│ │ 模糊半径 ═══════════════════════════════○═══ 8.0 │ │
│ │ 扩散半径 ═══════════════════════════════○═══ 0.0 │ │
│ │ 透明度 ═══════════════════════════════○═══ 0.25 │ │
│ └────────────────────────────────────────────────────────┘ │
│ 阴影颜色 [■] 内阴影 [○] │
└─────────────────────────────────────────────────────────────┘
3.5 状态管理
3.5.1 核心状态变量
// 阴影核心参数
double _offsetX = 0; // X轴偏移
double _offsetY = 4; // Y轴偏移
double _blurRadius = 8; // 模糊半径
double _spreadRadius = 0; // 扩散半径
double _shadowOpacity = 0.25; // 透明度
// 颜色相关
Color _shadowColor = Colors.black; // 阴影颜色
Color _boxColor = Colors.white; // 盒子颜色
Color _backgroundColor = Color(0xFFF5F5F5); // 背景颜色
// 盒子参数
double _boxWidth = 200; // 盒子宽度
double _boxHeight = 200; // 盒子高度
double _borderRadius = 16; // 圆角半径
// 功能状态
bool _isInset = false; // 是否内阴影
int _selectedPreset = -1; // 选中的预设索引
3.5.2 状态更新流程
// 滑块值变化时
void _updateOffsetX(double value) {
setState(() {
_offsetX = value;
_selectedPreset = -1; // 清除预设选中状态
});
}
四、UI设计规范
4.1 配色方案
应用采用简洁现代的设计风格:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | Indigo | AppBar、按钮 |
| 预览背景 | #F5F5F5 | 预览区域背景 |
| 代码背景 | Grey.shade900 | 代码块背景 |
| 代码文字 | GreenAccent | 代码高亮显示 |
| 分割线 | Divider | 区域分隔 |
4.2 组件样式
4.2.1 预览框样式
┌─────────────────────────────────────┐
│ │
│ ┌─────────────┐ │
│ │ │ │
│ │ Shadow │ ← 阴影效果 │
│ │ │ │
│ └─────────────┘ │
│ ↑ │
│ 阴影投影 │
│ │
└─────────────────────────────────────┘
4.2.2 预设卡片样式
| 属性 | 值 |
|---|---|
| 宽度 | 80px |
| 内边距 | 8px |
| 圆角 | 12px |
| 选中边框 | 2px 主色 |
| 未选中边框 | 1px 灰色 |
4.3 组件规范
4.3.1 参数滑块
┌─────────────────────────────────────────────────────────────┐
│ 水平偏移(X) ═══════════════════════════════○═══════ 0.0 │
│ ↑ ↑ ↑ ↑ │
│ 标签 滑块轨道 滑块 数值 │
└─────────────────────────────────────────────────────────────┘
4.3.2 代码块
┌─────────────────────────────────────────────────────────────┐
│ CSS [📋 复制] │
├─────────────────────────────────────────────────────────────┤
│ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.25); │
│ ↑ │
│ 绿色高亮代码 │
└─────────────────────────────────────────────────────────────┘
4.4 交互设计
4.4.1 操作方式
| 操作 | 手势 | 效果 |
|---|---|---|
| 调节参数 | 拖动滑块 | 实时更新阴影 |
| 选择预设 | 点击卡片 | 应用预设参数 |
| 选择颜色 | 点击色块 | 打开颜色选择器 |
| 复制代码 | 点击按钮 | 复制到剪贴板 |
4.4.2 视觉反馈
五、核心功能实现
5.1 预设效果初始化
void _initPresets() {
_presets.addAll([
ShadowPreset(
name: '柔和阴影',
shadows: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 10,
spreadRadius: 0,
offset: const Offset(0, 4),
),
],
code: 'box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);',
),
// ... 更多预设
]);
}
5.2 预设应用
void _applyPreset(int index) {
if (index < 0 || index >= _presets.length) return;
final preset = _presets[index];
final shadow = preset.shadows.first;
setState(() {
_selectedPreset = index;
_offsetX = shadow.offset.dx;
_offsetY = shadow.offset.dy;
_blurRadius = shadow.blurRadius;
_spreadRadius = shadow.spreadRadius;
_shadowColor = Color.fromRGBO(
shadow.color.r.toInt(),
shadow.color.g.toInt(),
shadow.color.b.toInt(),
1.0,
);
_shadowOpacity = shadow.color.a;
_isInset = preset.name == '内阴影';
});
}
5.3 滑块控制组件
Widget _buildSliderControl(
String label,
double value,
double min,
double max,
ValueChanged<double> onChanged, {
int? divisions,
}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
SizedBox(width: 100, child: Text(label)),
Expanded(
child: Slider(
value: value.clamp(min, max),
min: min,
max: max,
divisions: divisions ?? (max - min).toInt(),
onChanged: onChanged,
),
),
SizedBox(
width: 60,
child: Text(
value.toStringAsFixed(1),
textAlign: TextAlign.right,
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
],
),
);
}
5.4 颜色选择对话框
class _ColorPickerDialog extends StatefulWidget {
final Color initialColor;
// ...
}
class _ColorPickerDialogState extends State<_ColorPickerDialog> {
late double _hue;
late double _saturation;
late double _lightness;
late double _alpha;
Color get _currentColor {
return HSLColor.fromAHSL(_alpha, _hue, _saturation, _lightness).toColor();
}
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('选择颜色'),
content: Column(
children: [
// 颜色预览
Container(color: _currentColor),
// HSL滑块
_buildHueSlider(),
_buildSaturationSlider(),
_buildLightnessSlider(),
_buildAlphaSlider(),
// 预设颜色
Wrap(children: _presetColors.map(...).toList()),
],
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
FilledButton(onPressed: () => Navigator.pop(context, _currentColor), child: const Text('确定')),
],
);
}
}
5.5 复制到剪贴板
void _copyCode(String code, String type) {
Clipboard.setData(ClipboardData(text: code));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('$type 代码已复制到剪贴板'),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
}
六、阴影设计知识
6.1 阴影基本原理
6.1.1 光影关系
6.1.2 阴影类型
| 类型 | 特点 | 应用场景 |
|---|---|---|
| 外阴影 | 阴影在盒子外部 | 卡片、按钮 |
| 内阴影 | 阴影在盒子内部 | 凹陷效果、输入框 |
| 多层阴影 | 多个阴影叠加 | 高级效果 |
| 长投影 | 阴影延伸很长 | 扁平化设计 |
6.2 常用阴影效果
6.2.1 Material Design阴影层级
6.2.2 阴影参数对照
| 效果 | 偏移Y | 模糊 | 透明度 |
|---|---|---|---|
| 轻微阴影 | 2px | 4px | 0.1 |
| 标准阴影 | 4px | 8px | 0.15 |
| 明显阴影 | 8px | 16px | 0.2 |
| 深度阴影 | 12px | 24px | 0.25 |
6.3 阴影设计原则
| 原则 | 说明 |
|---|---|
| 一致性 | 同一应用使用统一的阴影风格 |
| 层次感 | 不同层级使用不同深度的阴影 |
| 适度性 | 阴影不宜过重,影响视觉体验 |
| 性能考虑 | 多层阴影会增加渲染开销 |
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 文字阴影
class TextShadowParams {
double offsetX;
double offsetY;
double blurRadius;
Color color;
}
| 功能 | 说明 |
|---|---|
| 文字阴影预览 | 实时显示文字阴影效果 |
| 多行文字支持 | 支持多行文字预览 |
| 字体选择 | 选择不同字体预览 |
7.2.2 渐变阴影
| 功能 | 说明 |
|---|---|
| 渐变方向 | 设置渐变方向 |
| 渐变颜色 | 多色渐变支持 |
| 渐变预览 | 实时预览效果 |
7.2.3 动画阴影
| 功能 | 说明 |
|---|---|
| 呼吸效果 | 阴影大小变化 |
| 颜色渐变 | 阴影颜色变化 |
| 位移动画 | 阴影位置变化 |
八、注意事项
8.1 开发注意事项
-
参数范围:确保滑块值在有效范围内
-
颜色转换:HSL与RGB转换精度问题
-
性能优化:避免频繁重建Widget
-
代码格式:生成的代码要格式化美观
8.2 用户体验优化
💡 用户体验建议 💡
- 参数变化时实时预览
- 提供常用预设快速选择
- 代码一键复制功能
- 支持深色模式适配
8.3 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 阴影不显示 | 透明度为0 | 调整透明度 |
| 颜色显示异常 | HSL转换错误 | 检查转换逻辑 |
| 代码复制失败 | 权限问题 | 检查剪贴板权限 |
| 预览卡顿 | 频繁重建 | 优化状态管理 |
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
9.2 运行命令
# 查看可用设备
flutter devices
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_shadow_generator.dart
# 运行到Windows
flutter run -d windows -t lib/main_shadow_generator.dart
# 代码分析
flutter analyze lib/main_shadow_generator.dart
十、总结
阴影生成器应用通过直观的可视化界面,让用户能够轻松创建各种阴影效果。应用支持水平偏移、垂直偏移、模糊半径、扩散半径、透明度等核心参数的精确调节,内置10种精心设计的预设效果,涵盖从基础到高级的各种阴影样式。
颜色选择器采用HSL色彩模式,支持色相、饱和度、亮度、透明度四个维度的精确调节,配合20种预设颜色,让颜色选择更加便捷。生成的CSS和Flutter代码格式规范,一键复制功能大幅提升开发效率。
界面设计简洁现代,预览区域实时展示阴影效果,参数调节区域布局合理,代码生成区域清晰直观。应用采用Material Design 3设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。
光影之间,设计之美,一键生成!
更多推荐


所有评论(0)