绘制K线第一章:可见区间处理

绘制K线第一章:可见区间处理

概述

在入门版本中,我们绘制了所有K线数据。但当数据量很大时,所有K线会挤在一起或超出屏幕,无法正常显示。

可见区间处理就是解决这个问题:只绘制屏幕能容纳的K线数量,让图表清晰可读。

为什么需要可见区间

问题场景

假设有以下情况:

  • 屏幕宽度:1080px
  • 每根K线占用:30px(20px宽度 + 10px间距)
  • 可显示的K线数量:1080 ÷ 30 = 36根
  • 实际数据:1000根K线

如果绘制所有1000根K线:

  • K线会挤在一起,无法看清
  • 或者超出屏幕,看不到完整内容

解决方案

只显示最后36根K线(最新的数据),这样:

  • K线清晰可读
  • 不会超出屏幕

实现原理

核心逻辑

scss 复制代码
// 1. 计算可见K线数量
val totalCandleWidth = config.getTotalCandleWidth()  // 30px
val visibleCount = (width / totalCandleWidth).toInt()  // 1080 ÷ 30 = 36

// 2. 获取可见数据(只取最后N根)
val visibleData = if (klineData.size > visibleCount) {
    klineData.takeLast(visibleCount)  // 取最后36根
} else {
    klineData  // 数据不足,全部显示
}

// 3. 只对可见数据计算价格范围
val priceRange = calculatePriceRange(visibleData)

// 4. 只绘制可见数据
visibleData.forEachIndexed { index, entity ->
    drawCandle(...)
}

关键点

  1. 计算可见数量屏幕宽度 ÷ 每根K线占用宽度
  2. 取最后N根 :使用 takeLast() 方法,显示最新的数据
  3. 价格范围计算:只基于可见数据计算,确保Y轴比例正确

代码实现(KLineViewCase2)

类图

kotlin 复制代码
@startuml
class KLineViewCase2 {
  - klineData: List<KLineEntity>
  - config: KLineConfig
  + setKLineData(data: List<KLineEntity>)
  - calculatePriceRange(data: List<KLineEntity>): Pair<Float, Float>
}

KLineViewCase2 --> KLineConfig : 依赖
KLineViewCase2 --> KLineEntity : 使用

note right of KLineViewCase2
  相比Case1,增加了可见区间处理:
  1. 计算可见K线数量
  2. 只取最后N根数据
  3. 只对可见数据计算价格范围
end note

@enduml

核心代码(可见区间部分)

onDraw() 方法中,相比Case1增加了可见区间处理:

scss 复制代码
// 1. 计算可见区间:根据屏幕宽度计算能显示多少根K线
val totalCandleWidth = config.getTotalCandleWidth()
val visibleCount = (width / totalCandleWidth).toInt()

// 2. 获取可见的K线数据(只显示最后N根,最新的数据)
val visibleData = if (klineData.size > visibleCount) {
    klineData.takeLast(visibleCount)  // 取最后N根
} else {
    klineData  // 数据不足,全部显示
}

// 3. 计算可见数据的价格范围(注意:传入visibleData而不是klineData)
val priceRange = calculatePriceRange(visibleData)

// 4. 绘制可见的K线(使用visibleData)
visibleData.forEachIndexed { index, entity ->
    drawCandle(canvas, entity, index, minPrice, maxPrice, height)
}

关键改动

  • calculatePriceRange() 方法现在接受 data 参数,可以传入可见数据
  • 其他绘制逻辑与Case1相同(参考入门文档)

与Case1的对比

特性 Case1(入门版) Case2(可见区间版)
绘制数据 所有数据 只绘制可见数据(最后N根)
价格范围计算 基于所有数据 基于可见数据
适用场景 数据量小(< 50根) 数据量大(> 50根)
代码复杂度 简单 稍复杂(增加可见区间逻辑)

完整绘制链路

相比Case1,Case2在绘制链路中增加了可见区间处理:

scss 复制代码
1. 设置K线数据 → 触发onDraw()重绘
   ↓
2. onDraw()方法执行:
   ├─ 绘制背景(与Case1相同)
   ├─ 检查数据是否为空(与Case1相同)
   ├─ 【新增】计算可见区间
   │   ├─ 计算可见K线数量(屏幕宽度 ÷ 每根K线宽度)
   │   └─ 获取可见数据(取最后N根)
   ├─ 计算价格范围(基于可见数据,不是所有数据)
   └─ 遍历可见K线数据并绘制(绘制逻辑与Case1相同)

说明:绘制K线的具体步骤(计算坐标、绘制影线、绘制实体)与Case1相同,参考入门文档。

关键概念

可见K线数量计算

scss 复制代码
可显示的K线数量 = 屏幕宽度 ÷ 每根K线占用的总宽度
                = width ÷ (candleWidth + candleSpacing)
                = width ÷ totalCandleWidth

示例

  • 屏幕宽度:1080px
  • 每根K线占用:30px(20px宽度 + 10px间距)
  • 可见数量:1080 ÷ 30 = 36根

取最后N根数据

arduino 复制代码
val visibleData = if (klineData.size > visibleCount) {
    klineData.takeLast(visibleCount)  // 取最后N根(最新数据)
} else {
    klineData  // 数据不足,全部显示
}

说明

  • 如果数据量 > 可见数量:只取最后N根(显示最新数据)
  • 如果数据量 ≤ 可见数量:全部显示

价格范围只基于可见数据

这是关键点:价格范围必须只基于可见数据计算,而不是所有数据。

为什么?

  • 如果基于所有数据计算价格范围,可见数据的价格变化可能很小
  • 导致Y轴比例不合适,K线看起来像一条线
  • 只基于可见数据计算,Y轴比例正确,K线清晰可见

注意事项

  1. 数据顺序 :确保数据是按时间顺序排列的(从旧到新),这样 takeLast() 才能取到最新数据
  2. 边界情况:当数据量小于可见数量时,需要全部显示
  3. 价格范围:必须只基于可见数据计算,不能基于所有数据

总结

可见区间处理是K线绘制的重要优化:

  • 解决数据量大时的显示问题
  • 只绘制屏幕能容纳的K线
  • 价格范围只基于可见数据计算
  • 为后续的滚动、缩放功能打下基础

效果

相关推荐
wangkay882 小时前
【Java 转运营】Day02:抖音直播间流量底层逻辑全解析
java·新媒体运营
5***b972 小时前
Spring Boot--@PathVariable、@RequestParam、@RequestBody
java·spring boot·后端
AIGCExplore2 小时前
Jenkins 全局配置及工具验证教程
java·servlet·jenkins
qq_318121592 小时前
Java大厂面试故事:Spring Boot、微服务与AI场景深度解析
java·spring boot·redis·微服务·ai·kafka·spring security
玛丽莲茼蒿3 小时前
javaSE 集合框架(五)——java 8新品Stream类
java·开发语言
程序员小假3 小时前
设计一个支持万人同时抢购商品的秒杀系统?
java·后端
L***d6703 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端
C雨后彩虹3 小时前
竖直四子棋
java·数据结构·算法·华为·面试
疾风sxp3 小时前
nl2sql技术实现自动sql生成之langchain4j SqlDatabaseContentRetriever
java·人工智能·langchain4j