需求是这样的, 要用 canvas 画出心电图,后端 1 秒给我传 1 个数组,数组里有 250 个数据 结构是这样的 https://nas-1253716007.cos.ap-guangzhou.myqcloud.com/mmexport1591493767956.png 但是呢,实际效果就是,渲染速度跟不上后端给我数据的速度。 我是用了 requestAnimationRequest 来循环渲染数据的。 想了一下,1 秒渲染 250 个数据,不就是 250 帧了吗,普通的屏幕才 60hz 的刷新率,感觉不可能做到的啊
1
zhouchijian OP 格式怎么乱掉了。。。
|
2
qiayue 2020-06-07 09:42:26 +08:00
抽稀
|
3
qiayue 2020-06-07 09:43:09 +08:00
合并、取样、抽稀
|
4
imdong 2020-06-07 09:47:40 +08:00
应该是一秒一帧,如何做到尽可能少的绘制。
看了你的格式,起码 0-36 这样的数据可以压缩为一次操作? 应该是类似折线图吧?最简单的能给出的意见就是这样。 连续在 dom 上绘制 速度比较慢,能不能把操作在内存绘制好,然后放到 dom 上呢? 一秒钟渲染一张图片应该问题不大,具体我也不懂,业余人士瞎比比。 |
5
cornetCat 2020-06-07 09:51:34 +08:00
1 秒渲染 250 个数据,不就是 250 帧了吗
这不对吧 想达到 60fps,应该是 1/60s 内渲染完 250 个数据 |
6
Perry 2020-06-07 09:52:37 +08:00
需求完全没说清楚,请先说清楚这 250 个数据是什么数据,需求是什么
|
7
MoHen9 2020-06-07 09:55:29 +08:00 via Android
每次多绘制几个点就行,人眼看不出来区别的,我在 Android 上也是这样做的,我们用 C++做的客户端也不会一次只绘制一个点,采样率有可能是 1000/s,难道也要每秒绘制 1000 次?
楼上方法也可以 |
8
hakono 2020-06-07 09:58:18 +08:00 via Android
我看你这数据,感觉是一秒渲染一次啊
如果后端给你的数据是每帧数据,先不提渲染赶不赶得上,你显示器首先刷新率绝对就没有 250Hz 吧,就算真渲染出了 250fps,你这也是没有任何用处啊。直接 250 个数据每隔 10 个取一个数,渲染成 25fps 人眼都感觉不太出区别 |
9
binux 2020-06-07 10:00:28 +08:00
250 个标量?别说 250 个了,25000 个都没问题
|
10
whileFalse 2020-06-07 10:00:33 +08:00 3
大哥,一秒传你一次数据,其中包含 250 个数,那其实是 1hz 啊……只不过每次屏幕更新要在已有数据基础上绘制 250 个点而已。如果忽略数据处理、网络传输、绘制等时间,数据从收集到展现的平均时间是 0.5s 。
当然,用户可以觉得这种仿照微软 windows 任务管理器的更新速度不够接地气,并愿意加一倍的钱让他更新速度变快。那你就可以每秒钟绘制 2 帧( 2hz ),并每帧绘制 125 个点。依照这种思路,只要用户肯出 60 倍的钱,你就可以每秒绘制 60 次,每次绘制 4 个点或 5 个点。你可以以 settimeout 方式执行每秒多次绘制。 如果用户肯出 100 倍的钱一劳永逸地完美地解决这个问题,那你就用 requestAnimationRequest 吧。你可以很简单地计算出上一次执行到本次执行之间用了多少毫秒,然后除以 4 (即 1000/250 ),得出你本次应该绘制的点的数量。此外,你还应该对上次绘制的图进行平移。 |
11
zhouchijian OP |
12
zhouchijian OP @MoHen9 有道理,每次只绘制一个点太蠢了
|
13
zhugefubin 2020-06-07 10:25:52 +08:00 via Android
一下绘制一组数据不行么
|
14
binbinyouliiii 2020-06-07 10:27:33 +08:00
4K 显示器有 3840*2160 个像素点,岂不是有 3840*2160 的刷新率
|
15
zhouchijian OP @imdong 其实就是折线图,但是要求有动画效果,就是类似于那种扫描效果,现在是每次只绘制一个点,你说的对,应该尽可能少的绘制
|
16
zhouchijian OP @zhugefubin 我也想这么简单粗暴,但是要有动画效果
|
17
7gugu 2020-06-07 10:58:19 +08:00 via Android
不考虑一下现有的图表库么?比如 Echarts 和 Uchart 等.
|
18
reus 2020-06-07 10:59:20 +08:00
你一秒渲染多少帧,和屏幕刷新率有什么关系?
那些游戏一秒几十几百帧,为什么可以显示? 一辆车从你眼前开过,你眨一下眼睛,难道车会根据你眨眼睛慢了,速度就变了? 显示器就是你的眼睛,只是在采样观察外部世界,而外部世界并不会受你的眼睛影响。 |
19
zhugefubin 2020-06-07 11:20:14 +08:00 via Android
我对这个不是很懂
@zhouchijian |
20
abelce 2020-06-07 11:36:07 +08:00 via iPhone
你一秒渲染一次就可以了呀,我以前渲染几十万个点都没毛病
|
21
zhouchijian OP @reus 对喔。。难道是我理解错刷新率了
|
22
zhouchijian OP @7gugu 不给用 echarts,原因我也不知道
|
23
zhouchijian OP @abelce 不行,要有动画,一秒渲染一次就没动画了
|
24
jackmod 2020-06-07 12:19:18 +08:00
markdown 要 2 次换行才是新段落,发之前点一下预览
|
25
reus 2020-06-07 12:57:34 +08:00 via Android
@zhouchijian 动画的话,每秒渲染 30 次左右就够了,也就是 256/32,每次渲染 8 个点,每 1000/32ms 渲染一次
|
26
reus 2020-06-07 12:58:28 +08:00 via Android
@zhouchijian 一秒一次就是 1hz 的动画,怎么叫没有?
|
27
rockjike 2020-06-07 13:29:25 +08:00 via Android
一桢更新 10 个数据,一个周期不一定要 1s,可以先把后端数据储存起来
|
28
Cabana 2020-06-07 13:37:52 +08:00 via Android
1 秒 250 个数据分成 25 帧,一帧绘制 10 个数据不行吗?
|
29
nightv2 2020-06-07 13:55:00 +08:00 via Android
比如说每秒在内存中把 250 个数据生成一个折线图,然后和上一秒的折线图做一个带有动画效果的切换,切换应该是有现成的轮子的
|
30
javaluo 2020-06-07 14:39:24 +08:00 via Android
每秒渲染一次,弄一个遮罩平行移动展示出来不就行了?
|
31
aturx 2020-06-07 14:49:38 +08:00 via Android
同事做过类似的,要动画效果,可以传数据的时候可以几秒传一组数据,渲染的时候频率高点持续渲染。
|
32
justin2018 2020-06-07 16:23:48 +08:00
|
33
zhouchijian OP @justin2018 对,就是这种效果
|
34
zhouchijian OP |
35
sarlanori 2020-06-07 16:39:01 +08:00 via Android
这个和我们绘制频谱图波形图是一样的,你这个相当于一秒一帧,一帧数据有 250 个点,你只需要连续绘制就可以了,每次数据来了就把可视区域内的数据重新绘制,自然就有了动态效果。
|
36
ghostheaven 2020-06-07 16:39:36 +08:00 via Android
动画和绘制的时间精确控制在一秒,开始的时候缓存几秒数据再开始
|
37
Torpedo 2020-06-07 16:41:55 +08:00
你延迟一秒画。
不就变成你有 250 个数据,然后在 1s 里,60 帧,每帧画 4 个。 |
38
reus 2020-06-07 20:25:19 +08:00
@zhouchijian 闪瞎眼……不要每次都重绘,做一下平移,然后渲染新的点就行了。这么闪,还不如用 svg,至少不闪……
|
39
jiejiss 2020-06-07 20:52:16 +08:00
动画效果 30Hz 足够用了,你每帧绘制 8 - 9 个点就行
但是 requestAnimationFrame 每帧之间的间隔不一定一样,比如设备卡了上一个 frame 和下一个 frame 之间间隔 1s 怎么办?所以你可以整个全局数组,拿 setInterval 以固定的频率(比如 30Hz )往里 push 数据,然后在 requestAnimationFrame 里把这个数组里的全部数据消费掉 |
40
jakezh 2020-06-07 22:08:24 +08:00
那我这种一秒渲染 50 万个数据的怎么算帧率?
|
41
zhouchijian OP @jakezh 那老哥你是怎么解决这种问题的
|
42
zhouchijian OP @reus 闪应该是正常的。。因为我每帧都绘制 10 个点了。。每 16ms 绘制一次,改成每帧绘制 4 个点就舒服多了。。至于 svg,刚开始我也想用 svg 的,因为项目的老代码也是用 canvas 来做心电图的,然后时间紧,就想着继续用 canvas,没有用 svg,因为以前也没写过 svg 。。
|
43
cheng6563 2020-06-07 23:05:34 +08:00 via Android
双缓冲,就不会闪了。。。。这不是基本操作吗
|
44
zhouchijian OP @cheng6563 不清楚耶,第一次搞这种图表
|
45
reus 2020-06-07 23:55:24 +08:00
@zhouchijian 用双缓冲: https://stackoverflow.com/questions/2795269/does-html5-canvas-support-double-buffering
就是不要直接清空,而是在另一个 canvas 里更新,更新完了再切换,就不会闪了 |
46
wangcheng 2020-06-08 00:33:58 +08:00
不应该假设 requestAnimationFrame 每 16ms 绘制一次,应该用 requestAnimationFrame 回调中的第一个参数时间戳来计算动画。否则帧率不是 60 的时候动画速度就乱了。
|
47
weixiangzhe 2020-06-08 09:35:17 +08:00 via Android
按比例采样吧,
|
48
redbuck 2020-06-08 14:27:03 +08:00
渲染和生成路径(即更新 view model)分开.
生成路径随便 push. 渲染按照固定频率把路径绘制到 canvas 上. |
49
jakezh 2020-06-08 21:37:24 +08:00
我是先渲染上,然后按照鼠标事件加动画。
没有你这种每秒全局刷新的需求 |