分段涂抹功能
项目简介:本模块适用于 Wi-Fi + BLE 协议的幻彩串灯(灯串)设备,支持对灯珠进行分段选择和独立控制,实现精确的灯光效果定制。
🖼️ 预览:
分段涂抹功能允许用户通过可视化界面选择特定的灯珠段,并对选中的灯珠段进行独立的颜色控制。该功能支持彩光和白光两种模式,可以实现全段控制、单段控制和分段涂抹等多种操作方式,是用户个性化灯光效果的重要工具。
功能列表
- 灯珠可视化显示:以网格形式展示所有灯珠,支持点击选择
- 全选/取消全选:一键选择或取消所有灯珠
- 分段选择:支持点击单个或多个灯珠进行选择
- 分段涂抹控制:对选中的灯珠段进行独立的颜色控制
- 全段涂抹控制:对所有灯珠进行统一的颜色控制
- 实时预览:滑动调节时实时更新灯带颜色显示
- 数据同步:灯珠颜色数据同步到云存储和设备
功能实现详解
实现概述
分段涂抹功能采用 Redux 管理选中状态,通过 paint_colour_1 DP 点进行数据下发。核心实现思路:
- 状态管理:使用 Redux 的
commonSlice管理选中灯珠列表(checkedIdList)和全选状态(stripCheckAll) - 数据流转:用户选择 → 更新 Redux 状态 → 颜色调节 → 构建 DP 数据 → 下发设备
- 涂抹模式:支持油漆桶模式(全段)和单点涂抹模式(分段)
- 数据持久化:灯珠颜色数据保存到云存储,支持跨会话恢复
核心组件
src/components/light-strip/index.tsx: 灯带可视化组件,负责灯珠的显示和选择交互src/components/light/index.tsx: 灯光控制主组件,整合分段涂抹和颜色控制逻辑src/redux/modules/commonSlice.ts: Redux 状态管理,存储选中灯珠列表和全选状态src/hooks/useDrawToolDataList.ts: 涂抹工具数据管理 Hook,处理灯珠数据的更新src/devices/protocols/paintColour1.ts:paint_colour_1DP 点的编解码器src/hooks/useStorageData.ts: 云存储数据管理 Hook
组件职责说明:
- LightStrip 组件:负责灯珠的可视化渲染和点击交互,维护选中状态的 UI 反馈
- Light 组件:整合颜色控制和分段涂抹逻辑,处理颜色变化和 DP 下发
- commonSlice:集中管理选中状态,提供状态更新方法
- useDrawToolDataList Hook:封装灯珠数据更新逻辑,处理全段和分段两种模式
数据流
sequenceDiagram
participant User as 用户
participant LightStrip as 灯带组件
participant Redux as Redux Store
participant Light as 灯光组件
participant Hook as 数据Hook
participant Protocol as 协议解析器
participant Device as 设备
participant Cloud as 云存储
User->>LightStrip: 点击选择灯珠
LightStrip->>Redux: 更新选中列表
Redux-->>LightStrip: 更新UI状态
User->>Light: 调节颜色
Light->>Hook: 调用更新函数
Hook->>Hook: 构建灯珠数据数组
Hook->>Protocol: 编码DP数据
Protocol->>Device: 下发paint_colour_1
Device-->>User: 显示效果
Hook->>Cloud: 保存灯珠颜色数据Mermaid 流程图
功能主流程图:
flowchart TD
A[进入灯光控制页面] --> B[加载灯珠数据]
B --> C[显示灯带可视化]
C --> D{用户操作}
D -->|点击灯珠| E[更新选中状态]
D -->|点击全选| F[切换全选状态]
D -->|调节颜色| G[获取选中灯珠]
E --> H[更新Redux状态]
F --> H
G --> I{是否全选}
I -->|是| J[全段涂抹模式]
I -->|否| K[分段涂抹模式]
J --> L[构建全段DP数据]
K --> M[构建分段DP数据]
L --> N[编码DP数据]
M --> N
N --> O[下发到设备]
O --> P[更新云存储]
P --> Q[实时预览效果]数据流转图:
sequenceDiagram
participant User as 用户操作
participant UI as UI组件
participant State as Redux状态
participant Logic as 业务逻辑
participant DP as DP协议
participant Device as 设备
participant Storage as 云存储
User->>UI: 选择灯珠
UI->>State: dispatch(updateCheckedIdList)
State-->>UI: 更新选中状态
User->>UI: 调节颜色
UI->>Logic: 获取选中灯珠列表
Logic->>Logic: 构建颜色数据数组
Logic->>DP: 编码paint_colour_1数据
DP->>Device: 下发DP指令
Device-->>User: 显示灯光效果
Logic->>Storage: 保存灯珠颜色数据组件交互图:
graph TB
A[Light组件] -->|使用| B[LightStrip组件]
A -->|使用| C[ColorLight组件]
A -->|使用| D[WhiteLight组件]
B -->|dispatch| E[Redux Store]
C -->|调用| F[useDrawToolDataList]
D -->|调用| F
F -->|使用| G[useStorageData]
F -->|编码| H[paintColour1协议]
H -->|下发| I[设备]
G -->|保存| J[云存储]状态变化图:
stateDiagram-v2
[*] --> 初始状态: 页面加载
初始状态 --> 选择灯珠: 用户点击
选择灯珠 --> 调节颜色: 选中完成
调节颜色 --> 滑动调节: 开始滑动
滑动调节 --> 实时预览: 颜色变化
实时预览 --> 松手确认: 停止滑动
松手确认 --> 下发DP: 构建数据
下发DP --> 更新存储: 成功回调
更新存储 --> 选择灯珠: 继续操作
更新存储 --> [*]: 完成关键代码片段
灯珠选择处理:
全选/取消全选:
分段涂抹数据更新:
彩光分段控制:
数据结构
选中状态数据结构(Redux):
paint_colour_1 DP 数据结构:
灯珠颜色数据数组:
涂抹模式枚举:
API 调用
DP 下发接口:
- DP 点:
paint_colour_1 - 调用方式:
structuredActions.paint_colour_1.set(data, options) - 数据格式:经过
SmearFormater编码的十六进制字符串 - 调用时机:
- 全段控制:用户调节颜色且全选状态时
- 分段控制:用户调节颜色且存在选中灯珠时
- 滑动调节:仅在松手时下发,滑动过程中只更新 UI
云存储接口:
- 存储键:
lightStripDataKey(常量定义) - 调用方式:
useSetStorageData(lightStripDataKey) - 数据格式:RGB 颜色字符串数组
- 调用时机:DP 下发成功后,更新云存储数据
注意事项
实现难点
-
选中状态同步:
- 难点:需要在多个组件间同步选中状态,确保 UI 和数据一致
- 解决方案:使用 Redux 集中管理状态,通过
useSelector和dispatch实现状态共享和更新
-
实时预览性能:
- 难点:滑动调节时需要实时更新大量灯珠颜色,可能造成性能问题
- 解决方案:使用节流(throttle)限制更新频率,滑动时只更新 UI,松手时才下发 DP
-
数据对齐:
- 难点:灯珠数量可能变化,需要确保数据数组长度与设备灯珠数量一致
- 解决方案:在
useCutDrawDiySceneSet中检查数据长度,不足时补全默认颜色,超出时截断
-
全选状态判断:
- 难点:需要准确判断是否所有灯珠都被选中
- 解决方案:通过比较选中集合大小和灯珠总数,使用
useEffect监听变化并更新全选状态
常见问题
-
问题:选择灯珠后调节颜色无效果
- 原因:未选中任何灯珠且未开启全选模式
- 解决方法:检查
checkedSet.size和stripCheckAll状态,提示用户先选择灯珠
-
问题:滑动调节时颜色更新延迟
- 原因:节流时间设置过长或 DP 下发过于频繁
- 解决方法:调整节流时间(建议 300ms),滑动时只更新 UI,松手时再下发 DP
-
问题:设备灯珠数量变化后数据不匹配
- 原因:云存储数据长度与设备灯珠数量不一致
- 解决方法:在数据加载时自动对齐,补全或截断数据数组
-
问题:全选状态显示不正确
- 原因:选中状态更新后未及时同步全选状态
- 解决方法:使用
useEffect监听选中列表变化,自动更新全选状态
性能优化
-
节流处理:
- 颜色调节使用节流,避免频繁更新
- 滑动时使用节流更新 UI,减少渲染次数
-
数据缓存:
- 使用
useRef缓存上一次的灯珠数据,避免重复更新 - 使用
useMemo缓存计算结果,减少重复计算
- 使用
-
条件渲染:
- 根据灯珠数量动态调整渲染层级,减少不必要的 DOM 节点
- 使用
useMemo缓存灯珠元素列表
-
状态更新优化:
- 批量更新状态,减少 Redux dispatch 次数
- 使用
useCallback缓存事件处理函数
边界情况
-
灯珠数量为 0:
- 处理:组件返回空视图,不进行渲染
- 代码:
if (!lightNum) return <View />;
-
未选中任何灯珠:
- 处理:提示用户先选择灯珠,不执行颜色更新
- 代码:检查
checkedSet.size === 0 && !isSectionAll
-
设备灯珠数量变化:
- 处理:自动对齐数据长度,补全或截断
- 代码:在
useCutDrawDiySceneSet中处理
-
DP 下发失败:
- 处理:显示错误提示,不更新云存储数据
- 代码:在
fail回调中处理错误
-
同时进行多个操作:
- 处理:使用
isPutDpIngReg标志位防止重复下发 - 代码:设置超时恢复机制(1 秒)
- 处理:使用