文章配图:模运算条件样式、三元表达式样式、enum 映射色、等级色函数四种套路

页面预览

前言

上一篇我们用双层 ForEach 把 5×8 棋盘网格渲出来,但每格背景色写的是 (row+col)%2 === 0 ? '#F0F4F8' : '#E6EDF3'——这个「模运算条件样式」一眼看似简单,实则是 ArkUI 响应式样式的核心套路:三元表达式根据数据动态返回样式值。这种套路在棋盘色、状态色、等级色、性别色等场景反复出现。

本篇以「猫猫大作战」棋盘隔行变色为锚点,把模运算条件样式、三元表达式样式、enum 映射色、等级色函数四种套路讲透。读完本篇你将能独立写出:棋盘格变色等级色映射状态色切换条件圆角四种动态样式。

提示:本系列不讲 ArkTS 基础语法与环境搭建,假设你已跟完第 1–13 篇。

一、场景拆解:棋盘色三元表达式

回顾 GameView 第 1 层棋盘背景:

// 来源:entry/src/main/ets/pages/Index.ets  GameView() 棋盘格
Stack() {
  Text('').fontSize(20)
}
.width(`${100 / COLS}%`).height(`${100 / ROWS}%`)
.backgroundColor((row + col) % 2 === 0 ? '#F0F4F8' : '#E6EDF3')

核心.backgroundColor(...) 的参数是一个三元表达式,根据 (row+col)%2 的奇偶性动态返回浅色或深色。

二、三元表达式在样式中的合法位

ArkUI 的属性方法(.fontSize/.backgroundColor/.borderRadius 等)接受任意返回合法类型的表达式——包括三元、函数调用、常量。

2.1 三元表达式样式

.backgroundColor((row + col) % 2 === 0 ? '#F0F4F8' : '#E6EDF3')
.fontSize(isTitle ? 20 : 14)
.borderRadius(isCard ? 12 : 0)
.fontColor(isActive ? '#2ECC71' : '#95A5A6')

语法条件 ? 真值 : 假值。条件为 true 返回真值,否则返回假值。

2.2 嵌套三元(多条件)

.backgroundColor(
  row === 0 ? '#FFC107' :       // 第 0 行黄(预警行)
  row === 1 ? '#E74C3C' :       // 第 1 行红(危险行)
  row === 2 ? '#FFFFFF' :       // 第 2 行白(安全行)
  '#F8F9FA'                      // 其余浅灰
)

嵌套三元用于多条件分支——但超过 3 层可读性崩,应改用函数(第 4 节讲)。

2.3 三元 vs if/else

// ✅ 三元:在属性参数里合法
.backgroundColor((row + col) % 2 === 0 ? '#F0F4F8' : '#E6EDF3')

// ❌ if/else:不能写在属性参数里
.backgroundColor(if (cond) { '#F0F4F8' } else { '#E6EDF3' })   // 语法错!

关键:ArkUI 属性参数里只能用三元,不能用 if/else——if 是语句不是表达式,没有返回值。

三、模运算的四种棋盘色套路

3.1 (row+col)%2 棋盘格(本项目)

(row + col) % 2 === 0 ? '#F0F4F8' : '#E6EDF3'

色分布:相邻格永远异色,经典棋盘。

行\列 0 1 2 3
0
1
2

3.2 row%2 行间变色

row % 2 === 0 ? '#F8F9FA' : '#FFFFFF'

色分布:相邻行异色,同行同色。适合列表项变色。

3.3 col%2 列间变色

col % 2 === 0 ? '#F8F9FA' : '#FFFFFF'

色分布:相邻列异色,同列同色。适合横向卡片变色。

3.4 (row*2+col)%3 三色循环

[(row * 2 + col) % 3, '#FFC107', '#FF9800', '#E74C3C']   // 伪代码,实际用函数

色分布:三色循环,视觉更丰富但易花,慎用。

四、enum 等级色映射实战

打开 GameTypes.ets,猫咪有 6 级:

export enum CatLevel {
  LEVEL_1,   // 0
  LEVEL_2,   // 1
  LEVEL_3,   // 2
  LEVEL_4,   // 3
  LEVEL_5,   // 4
  LEVEL_6    // 5
}

每级对应一个颜色,渲染时要根据 cat.level 返回对应色。嵌套三元写 6 层就崩,应改用函数 + switch

getCatColor(level: CatLevel): string {
  switch (level) {
    case CatLevel.LEVEL_1: return '#FFC107'    // 黄
    case CatLevel.LEVEL_2: return '#FF9800'    // 橙
    case CatLevel.LEVEL_3: return '#E74C3C'    // 红
    case CatLevel.LEVEL_4: return '#9B59B6'    // 紫
    case CatLevel.LEVEL_5: return '#2ECC71'    // 绿
    case CatLevel.LEVEL_6: return '#3498DB'    // 蓝
    default: return '#FFC107'
  }
}

// 使用:
Text(this.getCatEmoji(cat.level))
  .fontSize(30)
  .backgroundColor(this.getCatColor(cat.level))

4.1 Record 映射表替代 switch

const CAT_COLOR: Record<number, string> = {
  [CatLevel.LEVEL_1]: '#FFC107',
  [CatLevel.LEVEL_2]: '#FF9800',
  [CatLevel.LEVEL_3]: '#E74C3C',
  [CatLevel.LEVEL_4]: '#9B59B6',
  [CatLevel.LEVEL_5]: '#2ECC71',
  [CatLevel.LEVEL_6]: '#3498DB'
}

getCatColor(level: CatLevel): string {
  return CAT_COLOR[level] ?? '#FFC107'   // ?? 防空
}

Record 映射表优势

  • O(1) 查询:比 switch O(n) 快。
  • 数据驱动:颜色改一处即可,不动函数。
  • 易扩展:加级只需加一行。

提示:ArkTS 严格模式禁 anyRecord<K, V> 是真正的字典映射类型,替代 JS 的 {} 动态对象。本系列第 115 篇会专讲 Record

4.2 资源引用替代硬编码色

const CAT_COLOR: Record<number, Resource> = {
  [CatLevel.LEVEL_1]: $r('app.color.cat_level_1'),
  [CatLevel.LEVEL_2]: $r('app.color.cat_level_2'),
  // ...
}

$r('app.color.xxx') 资源引用替代 '#FFC107' 硬编码——暗色模式切换自动适配。本系列第 28 篇会专讲暗色模式。

五、状态色切换实战

GameState 也有色映射:

getGameStateColor(state: GameState): string {
  switch (state) {
    case GameState.IDLE: return '#95A5A6'      // 灰:待机
    case GameState.PLAYING: return '#2ECC71'   // 绿:游玩
    case GameState.PAUSED: return '#FFC107'    // 黄:暂停
    case GameState.GAME_OVER: return '#E74C3C' // 红:结束
    default: return '#95A5A6'
  }
}

// 使用:状态指示器
Circle({ width: 12, height: 12 }).fillColor(this.getGameStateColor(this.gameState))

状态色语义

状态 语义
IDLE 静默
PLAYING 绿 活跃
PAUSED 等待
GAME_OVER 警告

六、条件圆角实战

圆角也能用三元动态控:

// 棋盘格:方角
Stack() { /* ... */ }
  .borderRadius(0)

// 棋子:圆角
Text(this.getCatEmoji(cat.level))
  .borderRadius(cat.level >= 5 ? 50 : 12)   // 高级猫咪更圆,5+ 级用 50(近圆)

// 卡片:中圆角
Column() { /* ... */ }
  .borderRadius(isModal ? 24 : 12)          // 模态卡片更圆

条件圆角套路:根据数据动态控圆角,让视觉语义随状态变化。

七、完整代码:四种动态样式对比

7.1 棋盘色(三元表达式)

Stack() {
  Text('').fontSize(20)
}
.width(`${100 / COLS}%`).height(`${100 / ROWS}%`)
.backgroundColor((row + col) % 2 === 0 ? '#F0F4F8' : '#E6EDF3')

7.2 等级色(函数 + switch)

getCatColor(level: CatLevel): string {
  switch (level) {
    case CatLevel.LEVEL_1: return '#FFC107'
    case CatLevel.LEVEL_2: return '#FF9800'
    case CatLevel.LEVEL_3: return '#E74C3C'
    case CatLevel.LEVEL_4: return '#9B59B6'
    case CatLevel.LEVEL_5: return '#2ECC71'
    case CatLevel.LEVEL_6: return '#3498DB'
    default: return '#FFC107'
  }
}

Text(this.getCatEmoji(cat.level))
  .fontSize(30)
  .backgroundColor(this.getCatColor(cat.level))
  .borderRadius(8)

7.3 状态色(Record 映射表)

const STATE_COLOR: Record<number, string> = {
  [GameState.IDLE]: '#95A5A6',
  [GameState.PLAYING]: '#2ECC71',
  [GameState.PAUSED]: '#FFC107',
  [GameState.GAME_OVER]: '#E74C3C'
}

getGameStateColor(state: GameState): string {
  return STATE_COLOR[state] ?? '#95A5A6'
}

Circle({ width: 12, height: 12 }).fillColor(this.getGameStateColor(this.gameState))

7.4 条件圆角(三元嵌套)

Text(this.getCatEmoji(cat.level))
  .fontSize(30)
  .borderRadius(cat.level >= 5 ? 50 : 12)   // 5+ 级近圆,其余小圆角

八、调试技巧:动态样式怎么调

  1. console.info 打色值:Builder 里加 console.info('color', this.getCatColor(cat.level)),追实际渲染色。
  2. 临时固定色验证:把三元临时改成固定 '#F00'(红),看所有格是否都红——验证表达式是否被调用。
  3. 密钥冲突排查:格子少几个?查 (row+col)%2 是否依赖了重复的 row/col 值。
  4. 真机看色:预览器渲染接近真机,但某些色相可能因屏密度差异,以真机为准

九、性能与最佳实践

  1. 三元表达式比函数调用快:简单 2 分支用三元,避免函数调用开销。
  2. 复杂分支用函数 + switch/Record:超 3 分支别嵌套三元,可读性崩。
  3. Record 映射表 O(1) 查询:比 switch O(n) 快,大数据量必用。
  4. 资源引用替硬编码色$r('app.color.xxx') 支持暗色模式,硬编码不支持。

总结

本篇我们从棋盘隔行变色切入,掌握三元表达式条件样式、模运算四种棋盘色套路、enum 等级色映射(switch/Record)、状态色切换、条件圆角五大要点,并给出了四种动态样式的完整代码。核心要点:属性参数用三元非 if/else,简单 2 分支用三元,复杂分支用函数 + Record 映射,资源引用替硬编码

下一篇我们将继续游戏页,拆解猫咪渲染的 Emoji Text 与圆形背景。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐