赵淳美 发表于 2025-5-30 13:44:52

React-Native开发鸿蒙NEXT-svg绘制睡眠质量图part2

React-Native开发鸿蒙NEXT-svg绘制睡眠质量图part2

FBI WARNING:
The complete demo will be posted at the end of the series<Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>, so no need to worry.
https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/15db982a3fb8405cb4024b6d3f9df073~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oKs56m65YWr5Y-q6ISa:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjA0MTE1Mzk0NzE3Mzg1MyJ9&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1748871002&x-orig-sign=wD0Pp1RlH7Up31fFXr2V7A2ko0w%3D
上回进展到在画布上画出了睡眠采样点的数据,下面要做的是把同一阶段的相邻的点连接起来,让它具有形状。
先做个简单版的,类似excel那样用个方框连一连。
在svg中,可以用Rect来绘制一个矩形。基本的语法如下
            <Rect
            key={`connector-${areaData.areaIndex}`}
            x={areaData.aeraX}
            y={areaData.aeraY}
            width={areaData.areaWidth}
            height={areaData.areaHeight}
            /><Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,知道起点坐标加上宽高即可。首先创建一个areaData数组,用于记录矩形的绘制矩形的基本信息(暂时只要关注areaIndex<Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,areaX,areaY,areaWidth,areaHeight)
interface SleepAreaData {
areaIndex: number; // 区域索引
aeraX: number; // 区域X坐标
aeraY: number; // 区域Y坐标
areaWidth: number; // 区域宽度
areaHeight: number; // 区域宽度
areaColor: any | null; // 区域颜色
areaStoke: any | null; // 区域阴影
areaLeftUpDown: UpDownEnum; // 区域左边上升下降趋势
areaRightUpDown: UpDownEnum; // 区域左边上升下降趋势
areaStage: number; // 睡眠阶段
areaBeginIndex: number; // 区域开始索引
areaEndIndex: number; // 区域结束索引
}接着开始遍历画布上的数据点集合points,循环计算用于构建一个SleepAreaData数组,每计算出一个SleepAreaData对象,同时创建一个Rect对象。
const calcPointData = () => {    let areaData = initAreaData();    let svgsTemp: JSX.Element[] = [];    points.map((point<Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>, index) => {      if (index == 0) {      areaData.areaIndex = index;      areaData.aeraX = point.x;      areaData.aeraY = point.y;      areaData.areaWidth = 0;      areaData.areaColor = `url(#gradient${point.stage})`;      areaData.areaStoke = STAGE_CONFIG.shadow;      areaData.areaLeftUpDown = UpDownEnum.UP;      areaData.areaStage = point.stage;      areaData.areaBeginIndex = index;      }      if (index - 1 >= 0) {      const prevPoint = points;      const isSameStage = point.stage === prevPoint.stage;      areaData.areaWidth += point.x - prevPoint.x;      let deltaY1 = 0;      let deltaY2 = 0;      if (!isSameStage) {          if (point.stage > prevPoint.stage) {            deltaY1 = -AREA_HEIGHT;          } else {            deltaY2 = -AREA_HEIGHT;          }          areaData.areaEndIndex = index;          console.log('areaData.areaEndIndex = ' + index);          areaDataList.push(areaData);          // 输出          svgsTemp.push(            <Rect
            key={`connector-${areaData.areaIndex}`}
            x={areaData.aeraX}
            y={areaData.aeraY}
            width={areaData.areaWidth}
            height={areaData.areaHeight}
            /><Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,          );          // 重新开始绘制矩形          areaData = initAreaData();          areaData.areaIndex = index;          areaData.aeraX = point.x;          areaData.aeraY = point.y;          areaData.areaWidth = 0;          areaData.areaColor = STAGE_CONFIG.color;          areaData.areaStoke = STAGE_CONFIG.shadow;          areaData.areaStage = point.stage;          areaData.areaBeginIndex = index;          if (point.stage > prevPoint.stage) {            areaData.areaLeftUpDown = UpDownEnum.UP;          } else {            areaData.areaLeftUpDown = UpDownEnum.DOWN;          }      }      }      if (index == points.length - 1) {      areaData.areaRightUpDown = UpDownEnum.DOWN;      areaData.areaEndIndex = index;      // 输出      areaDataList.push(areaData);      svgsTemp.push(            <Rect
            key={`connector-${areaData.areaIndex}`}
            x={areaData.aeraX}
            y={areaData.aeraY}
            width={areaData.areaWidth}
            height={areaData.areaHeight}
            /><Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,      );      }    });    return svgsTemp;};最终,这个方法向svg画布直接输出了一个Rect对象数组。
      {/* 可视化图表 */}
      <Svg height={CHART_HEIGHT + 80} width={SCREEN_WIDTH}>
      ......
      {/* 绘制 */}
      {data.length > 1 && calcPointData()}
      ......
      </Svg>可以看到,相邻的阶段被用矩形连接了起来。
https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/82eff0a6ffbd4bfc82f2c6f2476c817b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oKs56m65YWr5Y-q6ISa:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjA0MTE1Mzk0NzE3Mzg1MyJ9&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1748871002&x-orig-sign=XppKjk9wq578yHYsP1bCOO3h9bQ%3D
通过同时显示矩形和点,可以很直观地感受到上回说到的一个最重要的逻辑:
https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/e830ee83b82645a8902982dddfd66e74~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oKs56m65YWr5Y-q6ISa:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjA0MTE1Mzk0NzE3Mzg1MyJ9&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1748871002&x-orig-sign=8mD9tkDwCxYqE40nkDAH6jkbRtg%3D
下一步的想法就是给这些方块做下圆角,上点颜色,再看看是否能做个渐变色,这样至少颜色上可以做到竞品的效果。这些Rect都支持
<Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/8258f07448144e0ab251c2e18c3b59db~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oKs56m65YWr5Y-q6ISa:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjA0MTE1Mzk0NzE3Mzg1MyJ9&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1748871002&x-orig-sign=gTA2s%2FtdDtQyhkK1AqFMVWOEGUw%3D
把上下相邻的两个阶段方块间加上虚线连接,线段的设置逻辑同样是在calcPointData中
......// 出一条线if (index != data.length - 1) {svgsTemp.push(    <Rect
key={`connector-${areaData.areaIndex}`}
x={areaData.aeraX}
y={areaData.aeraY}
width={areaData.areaWidth}
height={areaData.areaHeight}
stroke={areaData.areaStoke}
fill={areaData.areaColor}
rx={5}
ry={5}
/>,);}// 重新开始绘制矩形areaData = initAreaData();areaData.areaIndex = index;areaData.aeraX = point.x;areaData.aeraY = point.y;areaData.areaWidth = 0;加上虚线连接,关掉数据点的显示后,此时的效果和网上为数不多的几个绘制睡眠图的开源库已经较为接近了
https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/f90e04bfcc184cf3bd8573281124d97f~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5oKs56m65YWr5Y-q6ISa:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjA0MTE1Mzk0NzE3Mzg1MyJ9&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1748871002&x-orig-sign=Jqq1QAUbfDk%2BcCfm3pXDH%2BDkR%2FM%3D
至此还剩下最后一步---把图上的矩形换成自定义的图形,根据不同阶段使用不同的图形样式。
To Be Continued...
不经常在线,有问题可在微信公众号或者掘金社区私信留言
更多内容可关注
我的公众号悬空八只脚

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

蜴间囝 发表于 2025-10-13 16:04:16

谢谢分享,辛苦了

迭婵椟 发表于 2025-11-8 00:18:06

不错,里面软件多更新就更好了

冷晓晴 发表于 2025-12-20 15:26:09

yyds。多谢分享

颜清华 发表于 2026-1-4 13:39:54

前排留名,哈哈哈

步雪卉 发表于 2026-1-8 17:41:09

喜欢鼓捣这些软件,现在用得少,谢谢分享!

毋献仪 发表于 2026-1-13 07:27:37

这个好,看起来很实用

愤血冒 发表于 2026-1-14 15:14:17

热心回复!

馏栩梓 发表于 2026-1-18 02:30:25

这个有用。

衣旱 发表于 2026-1-18 04:51:14

鼓励转贴优秀软件安全工具和文档!

谅潭好 发表于 2026-1-20 07:57:15

热心回复!

喳谍 发表于 2026-1-23 06:45:33

新版吗?好像是停更了吧。

晦险忿 发表于 2026-1-27 05:53:09

鼓励转贴优秀软件安全工具和文档!

拙因 发表于 2026-1-29 03:58:45

谢谢楼主提供!

萨瑞饨 发表于 2026-1-30 06:46:44

不错,里面软件多更新就更好了

篁瞑普 发表于 2026-2-1 02:48:55

新版吗?好像是停更了吧。

瘴锲如 发表于 2026-2-4 03:21:05

分享、互助 让互联网精神温暖你我

骆贵 发表于 2026-2-4 10:09:20

这个好,看起来很实用

赏勿 发表于 2026-2-4 10:55:08

懂技术并乐意极积无私分享的人越来越少。珍惜

坏级尹 发表于 2026-2-5 03:50:32

谢谢分享,试用一下
页: [1] 2
查看完整版本: React-Native开发鸿蒙NEXT-svg绘制睡眠质量图part2