chart_page.lua 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. --[[
  2. @module chart_page
  3. @summary 图表组件演示页面
  4. @version 1.0
  5. @date 2026.03.02
  6. @author 自动生成
  7. @usage
  8. 本文件是图表组件的演示页面,展示图表的各种用法。
  9. 注意:需要确保 airui.chart 组件可用。
  10. ]]
  11. local chart_page = {}
  12. ----------------------------------------------------------------
  13. -- 页面UI元素
  14. ----------------------------------------------------------------
  15. local main_container = nil
  16. local scroll_container = nil
  17. local chart_timer = nil -- 数据推送定时器ID
  18. local page_active = false -- 页面是否活跃,用于定时器安全
  19. local value_text = nil -- 显示当前数值
  20. local point_text = nil -- 显示按下的点索引
  21. local chart = nil -- 图表对象
  22. ----------------------------------------------------------------
  23. -- 辅助函数:创建带标题的容器
  24. ----------------------------------------------------------------
  25. local function create_demo_container(parent, title, x, y, width, height)
  26. local container = airui.container({
  27. parent = parent,
  28. x = x,
  29. y = y,
  30. w = width,
  31. h = height,
  32. color = 0xFFFFFF,
  33. radius = 8,
  34. })
  35. airui.label({
  36. parent = container,
  37. text = title,
  38. x = 10,
  39. y = 5,
  40. w = width - 20,
  41. h = 25,
  42. color = 0x333333,
  43. font_size = 14,
  44. })
  45. return container
  46. end
  47. ----------------------------------------------------------------
  48. -- 创建UI
  49. ----------------------------------------------------------------
  50. function chart_page.create_ui()
  51. main_container = airui.container({
  52. parent = airui.screen,
  53. x = 0,
  54. y = 0,
  55. w = 320,
  56. h = 480,
  57. color = 0xF5F5F5,
  58. })
  59. -- 标题栏
  60. local title_bar = airui.container({
  61. parent = main_container,
  62. x = 0,
  63. y = 0,
  64. w = 320,
  65. h = 50,
  66. color = 0x9C27B0, -- 紫色,与其他页面区分
  67. })
  68. airui.label({
  69. parent = title_bar,
  70. text = "图表组件演示",
  71. x = 10,
  72. y = 15,
  73. w = 200,
  74. h = 20,
  75. font_size = 16,
  76. color = 0xFFFFFF,
  77. })
  78. -- 返回按钮
  79. local back_btn = airui.button({
  80. parent = title_bar,
  81. x = 250,
  82. y = 10,
  83. w = 60,
  84. h = 30,
  85. text = "返回",
  86. on_click = function(self)
  87. go_back()
  88. end
  89. })
  90. -- 滚动容器(确保所有内容可滚动)
  91. scroll_container = airui.container({
  92. parent = main_container,
  93. x = 0,
  94. y = 50,
  95. w = 320,
  96. h = 420, -- 留出底部空间
  97. color = 0xF5F5F5,
  98. })
  99. local current_y = 10
  100. --------------------------------------------------------------------
  101. -- 示例说明
  102. --------------------------------------------------------------------
  103. airui.label({
  104. parent = scroll_container,
  105. text = "图表组件演示 (10Hz 模拟数据)",
  106. x = 10,
  107. y = current_y,
  108. w = 300,
  109. h = 20,
  110. font_size = 14,
  111. color = 0x333333,
  112. })
  113. current_y = current_y + 25
  114. --------------------------------------------------------------------
  115. -- 数值显示区域
  116. --------------------------------------------------------------------
  117. local info_container = airui.container({
  118. parent = scroll_container,
  119. x = 10,
  120. y = current_y,
  121. w = 300,
  122. h = 40,
  123. color = 0xEEEEEE,
  124. radius = 4,
  125. })
  126. current_y = current_y + 45
  127. value_text = airui.label({
  128. parent = info_container,
  129. text = "当前值: 50",
  130. x = 10,
  131. y = 10,
  132. w = 140,
  133. h = 20,
  134. font_size = 14,
  135. color = 0x333333,
  136. })
  137. point_text = airui.label({
  138. parent = info_container,
  139. text = "按下点: -1",
  140. x = 160,
  141. y = 10,
  142. w = 130,
  143. h = 20,
  144. font_size = 14,
  145. color = 0x333333,
  146. })
  147. --------------------------------------------------------------------
  148. -- 图表组件
  149. --------------------------------------------------------------------
  150. local chart_container = create_demo_container(scroll_container, "实时曲线", 10, current_y, 300, 200)
  151. current_y = current_y + 200 + 10
  152. chart = airui.chart({
  153. parent = chart_container,
  154. x = 10,
  155. y = 30,
  156. w = 280,
  157. h = 150,
  158. y_min = 0,
  159. y_max = 100,
  160. point_count = 30, -- 减少点数以适应窄屏
  161. update_mode = "shift", -- 滚动模式
  162. line_color = 0x00b4ff,
  163. line_width = 2,
  164. hdiv = 5,
  165. vdiv = 4,
  166. on_point = function(self)
  167. if point_text then
  168. local idx = self:get_pressed_point()
  169. point_text:set_text("按下点: " .. tostring(idx))
  170. log.info("chart", "pressed index", idx)
  171. end
  172. end
  173. })
  174. -- 预置一组初始值(平滑过渡)
  175. chart:set_values({50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 68, 66, 64, 62, 60, 58, 56, 54, 52, 50})
  176. --------------------------------------------------------------------
  177. -- 控制按钮区域
  178. --------------------------------------------------------------------
  179. local control_container = create_demo_container(scroll_container, "控制面板", 10, current_y, 300, 100)
  180. current_y = current_y + 100 + 10
  181. local mode = "shift"
  182. local btn_mode = airui.button({
  183. parent = control_container,
  184. text = "模式: shift",
  185. x = 20,
  186. y = 30,
  187. w = 120,
  188. h = 35,
  189. on_click = function(self)
  190. if mode == "shift" then
  191. mode = "circular"
  192. chart:set_update_mode("circular")
  193. self:set_text("模式: circular")
  194. else
  195. mode = "shift"
  196. chart:set_update_mode("shift")
  197. self:set_text("模式: shift")
  198. end
  199. log.info("chart", "update_mode ->", mode)
  200. end
  201. })
  202. local btn_clear = airui.button({
  203. parent = control_container,
  204. text = "清除",
  205. x = 160,
  206. y = 30,
  207. w = 120,
  208. h = 35,
  209. on_click = function(self)
  210. chart:clear(50)
  211. if value_text then
  212. value_text:set_text("当前值: 50")
  213. end
  214. log.info("chart", "clear to 50")
  215. end
  216. })
  217. local btn_color = airui.button({
  218. parent = control_container,
  219. text = "随机颜色",
  220. x = 20,
  221. y = 70,
  222. w = 120,
  223. h = 35,
  224. on_click = function(self)
  225. local color = math.random(0, 0xFFFFFF)
  226. chart:set_line_color(color)
  227. log.info("chart", "set line color", string.format("%06X", color))
  228. end
  229. })
  230. --------------------------------------------------------------------
  231. -- 底部提示
  232. --------------------------------------------------------------------
  233. airui.label({
  234. parent = main_container,
  235. text = "提示: 点击曲线可查看数据点索引",
  236. x = 10,
  237. y = 450,
  238. w = 300,
  239. h = 20,
  240. color = 0x666666,
  241. font_size = 12,
  242. })
  243. end
  244. ----------------------------------------------------------------
  245. -- 定时器回调:模拟10Hz数据推送
  246. ----------------------------------------------------------------
  247. local function chart_timer_cb()
  248. if not page_active then
  249. return -- 页面已销毁,不再更新
  250. end
  251. -- 简单的三角波模拟
  252. local tick = _G.__chart_tick or 0
  253. tick = tick + 1
  254. _G.__chart_tick = tick
  255. local base = 50 + 30 * math.sin(tick * 0.1)
  256. local noise = math.random(-3, 3)
  257. local value = math.floor(base + noise + 0.5)
  258. -- 限制范围
  259. if value < 0 then value = 0 end
  260. if value > 100 then value = 100 end
  261. if chart and value_text then
  262. chart:push(value)
  263. value_text:set_text("当前值: " .. tostring(value))
  264. end
  265. if tick % 50 == 0 then
  266. log.info("chart", "running 10Hz, sample=", value)
  267. end
  268. end
  269. ----------------------------------------------------------------
  270. -- 初始化页面
  271. ----------------------------------------------------------------
  272. function chart_page.init(params)
  273. chart_page.create_ui()
  274. page_active = true
  275. -- 启动定时器(100ms = 10Hz)
  276. if chart_timer then
  277. sys.timerStop(chart_timer)
  278. end
  279. chart_timer = sys.timerLoopStart(chart_timer_cb, 100)
  280. end
  281. ----------------------------------------------------------------
  282. -- 清理页面
  283. ----------------------------------------------------------------
  284. function chart_page.cleanup()
  285. page_active = false
  286. if chart_timer then
  287. sys.timerStop(chart_timer)
  288. chart_timer = nil
  289. end
  290. if main_container then
  291. main_container:destroy()
  292. main_container = nil
  293. scroll_container = nil
  294. value_text = nil
  295. point_text = nil
  296. chart = nil
  297. end
  298. end
  299. return chart_page