K线图
技术难点
value 对应的纵坐标
已知数据里的最大值maxValue
、最小值minValue
、y 轴的高度yAxisHeight
,那么就可以得到 value 与yAxisHeight
的比例ratio
。想要得到刻度对应的数值,只需要将最小值+刻度间距iratio即可。
比如最大值 1000,最小值 500,y 轴高度为 100px,那么 1px 所代表(1000 - 500) / 100
,即 5。
如果 y 轴刻度间距为 30px,那么对应的数值为500 + 30*i*ratio
1 | /** |
x 轴元素动态隔点展示
x 轴元素的数量是处于变化的,但 x 轴宽度是已知的,这样我们就能算出元素之间的间距xAxisItemSpace
是多少。知道了xAxisItemSpace
,那我们就能知道 x 轴刻度横坐标。
1 | /** |
缩放时,考虑当元素太多时,如果展示所有的元素,会出现拥挤的情况。所以我们只能展示部分元素。
隔点展示:
1 | // 绘制x轴刻度与文字 |
三次贝塞尔曲线前后控制点
受前后元素纵坐标影响,由前后两个点和当前点的纵坐标构成一个平行四边形,即可得到当前元素的前后控制点。
还需要考虑首尾元素没有前后控制点的边界问题,所以要加入两个虚拟点。
辅助线
在 canvas 里,更新画布既是重选渲染整个画布,所以辅助线的绘制采用分层处理,创建一个新的画布覆盖上去,独立开来,不影响展示画布。
- 监听鼠标移动事件
mousemove
- 清除画布
- 如果在 gird 区域,绘制辅助线和提示框
拖拽
- 监听鼠标按下事件
mousedown
,并创建拖动元素。可以做记忆化处理(优化手段) - 监听开始拖动目标元素事件
dragstart
,并记录光标位置,即event.offsetX
- 监听拖动事件
drag
,拖动过程中,达到一定距离,清除画布(clearRect),然后更新要展示的数据,重新渲染即可 - 拖动结束时,需要隐藏拖动元素,并且如果左侧临时集合数据小于页数
pageSize
,请求接口数据
缩放
- 监听滚轮事件
wheel
- 放大
event.deltaY > 0
时,删除展示集合dataSource
前后数据,并分别扔到存储被删除数据的临时集合里,直到最小展示条数 - 缩小时「尽可能多的展示数据」,分两个情况,
- 当已展示条数大于最大展示条数时 或 左侧临时集合条数小于最小展示条数时,请求接口并将请求数据合并到左侧临时集合中
- 删除临时集合的数据,并扔到展示集合中
- 处理完数据,清除画布,重新渲染
应用层的思考
数据如何来:
初始时,默认展示为 10 条pageSize=10
,最大展示条数为 20 条maxShowSize = pageSize*2
,所以需要预准备 30 条数据pageSize+maxShowSize
,也就是首次加载 30 条数据。
更新时
- 拖拽什么时候请求新数据:拖拽结束后请求新数据
因为一次最多拖maxShowSize
,当左侧临时集合数据小于**maxShowSize**
时,请求接口数据,请求maxShowSize
条
- 缩放什么时候请求新数据:缩放结束后,当左侧临时集合数据小于
**maxShowSize**
时
因为没有缩放结束事件,我们可以观察下缩放时的时间间隔,在wheel
事件里打印Date.now()
,发现滚动时间间隔在 200ms 以内,保险起见我们取个 500ms。
当滚动时间超过了 500ms,我们就判断为滚动结束:
1 | let timer = null; |