@damoqiongqiu/ice-chart 0.30.0 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -118,7 +118,36 @@ export interface SeriesRawPoints {
118
118
  yDomain: [number, number] | null;
119
119
  xMonotonic: boolean;
120
120
  sizeExtent: [number, number] | null;
121
+ /**
122
+ * **去重后的 x 类目**(按首次出现顺序)与它们的出现次数 —— 增量维护。
123
+ *
124
+ * 为什么要有它:类目轴每次归一化都要这张表(`buildCategoryValues` / `buildXDomain`),
125
+ * 而滚动窗口的追加只动**两头**。不增量维护的话,10 万根的窗口每 tick 要重扫两趟 O(n)
126
+ * (实测:K 线环形追加 4.8ms/tick,其中 ~3ms 就是这两趟)。
127
+ * 追加 / 淘汰时各 O(1) 更新:新 key 追加到尾部,计数归零的 key 从表里摘掉。
128
+ */
129
+ categories: any[];
130
+ categoryCounts: Map<string, number>;
131
+ /**
132
+ * **类目 → 绝对序号**(首次出现在当前窗口里时分配的单调递增号)—— 增量维护。
133
+ *
134
+ * 为什么不把「下标」当值:滚动窗口每 tick 从头部淘汰一项,所有下标都要减一,
135
+ * 那样的表每帧都得整体重写(O(n))。存**绝对序号**之后,淘汰只删一个 key,
136
+ * 「下标」由一个基准量相减得到(见 `rawCategoryIndex`)。
137
+ */
138
+ categorySeq: Map<string, number>;
139
+ /** 下一个要分配的绝对序号。不变式:`首项序号 + 类目数`。 */
140
+ categoryNext: number;
121
141
  }
142
+ /**
143
+ * 类目在**当前** `categories` 里的下标 —— O(1),给类目轴的 `BandScale.indexOf` 当查表口。
144
+ *
145
+ * 依据:绝对序号按「首次出现顺序」分配,而 `categories` 正是按首次出现顺序排的,
146
+ * 所以存活类目的序号是**连续的一段**(头部淘汰只让这段整体后移;万一出现空洞,
147
+ * `removeCategory` 会就地压紧)。于是「下标 = 自己的序号 − 首项序号」。
148
+ * 调用方负责把类目 `String` 化(与 `BandScale` 的查表契约一致)。
149
+ */
150
+ export declare function rawCategoryIndex(store: SeriesRawPoints, key: string): number;
122
151
  export interface InternalSeries {
123
152
  id: string;
124
153
  index: number;
@@ -247,6 +276,23 @@ export declare function toNumber(value: any): number | null;
247
276
  * 「惰性原始点」存储(`rawAccessors`)。两边必须是同一份规则 —— 否则「普通系列」与
248
277
  * 「virtual 系列」合成出来的 `xValue / y / name / size` 会分叉,提示框和命中跟着漂。
249
278
  */
279
+ export declare function readGenericPointInto(item: any, index: number, option: {
280
+ type?: string;
281
+ xField?: string;
282
+ yField?: string;
283
+ }, out: {
284
+ xValue: any;
285
+ y: number | null;
286
+ size?: number;
287
+ name?: string;
288
+ explicitX: boolean;
289
+ }): typeof out;
290
+ /**
291
+ * 取点(分配版):普通系列与列存的 `pointAt` 用。
292
+ *
293
+ * **热循环请用 `readGenericPointInto` + 复用同一个 scratch**:这个版本每次调用都会
294
+ * new 一个对象,10 万项的域重算就是每 tick 10 万个短命对象(实测过,GC 直接顶上来)。
295
+ */
250
296
  export declare function readGenericPoint(item: any, index: number, option: {
251
297
  type?: string;
252
298
  xField?: string;
@@ -294,6 +340,14 @@ export interface InternalAxis {
294
340
  index: number;
295
341
  /** y 轴位置(x 轴为 left,不使用)。 */
296
342
  position: 'left' | 'right';
343
+ /**
344
+ * 类目轴的**现成查表口**(可选):`类目 key → 下标`,O(1)。
345
+ *
346
+ * 只有「域原样来自某个增量维护的类目表、且没有被视窗裁剪」时才给得出来
347
+ * (见 `buildXDomain`)。给了它等于告诉 `BandScale`:不必自己重建索引表 ——
348
+ * 10 万类目的滚动窗口每帧重建一次那张 Map,曾是整条流水线最大的一笔。
349
+ */
350
+ categoryLookup?: (key: string) => number;
297
351
  }
298
352
  export interface NormalizedOption {
299
353
  /** 场景类型:直角坐标 / 极坐标(饼图)/ 雷达图 / 桑基图。 */
@@ -360,6 +414,16 @@ export interface AxisLayout {
360
414
  ticks: any[];
361
415
  /** 刻度标签文本。 */
362
416
  labels: string[];
417
+ /**
418
+ * **惰性格式化**:`labels[i] === ''` 且给了这个函数时,第 i 颗的文本要现算(可选)。
419
+ *
420
+ * 类目轴一个数据点一个刻度,而真正画得出来的只有抽稀后那几百颗 —— 稠密轴(> 512 颗)
421
+ * 因此只在布局那一趟格式化**量宽度用的样本**,其余留空,抽稀定稿后由
422
+ * `thinXAxisLabels` 按留下来的下标现算。数值 / 时间轴刻度本来就少,走全量那条路。
423
+ */
424
+ formatLabel?: (index: number) => string;
425
+ /** 布局那一趟按样本量到的最大标签宽度(惰性格式化时 `labels` 里只有样本,不能再抽样)。 */
426
+ sampledLabelWidth?: number;
363
427
  /** 该轴相对绘图区边缘外扩的像素距离(多轴时同侧的轴逐层外移)。 */
364
428
  offset: number;
365
429
  /** 刻度标签的最大宽度 / 高度(像素)。 */
@@ -118,7 +118,36 @@ export interface SeriesRawPoints {
118
118
  yDomain: [number, number] | null;
119
119
  xMonotonic: boolean;
120
120
  sizeExtent: [number, number] | null;
121
+ /**
122
+ * **去重后的 x 类目**(按首次出现顺序)与它们的出现次数 —— 增量维护。
123
+ *
124
+ * 为什么要有它:类目轴每次归一化都要这张表(`buildCategoryValues` / `buildXDomain`),
125
+ * 而滚动窗口的追加只动**两头**。不增量维护的话,10 万根的窗口每 tick 要重扫两趟 O(n)
126
+ * (实测:K 线环形追加 4.8ms/tick,其中 ~3ms 就是这两趟)。
127
+ * 追加 / 淘汰时各 O(1) 更新:新 key 追加到尾部,计数归零的 key 从表里摘掉。
128
+ */
129
+ categories: any[];
130
+ categoryCounts: Map<string, number>;
131
+ /**
132
+ * **类目 → 绝对序号**(首次出现在当前窗口里时分配的单调递增号)—— 增量维护。
133
+ *
134
+ * 为什么不把「下标」当值:滚动窗口每 tick 从头部淘汰一项,所有下标都要减一,
135
+ * 那样的表每帧都得整体重写(O(n))。存**绝对序号**之后,淘汰只删一个 key,
136
+ * 「下标」由一个基准量相减得到(见 `rawCategoryIndex`)。
137
+ */
138
+ categorySeq: Map<string, number>;
139
+ /** 下一个要分配的绝对序号。不变式:`首项序号 + 类目数`。 */
140
+ categoryNext: number;
121
141
  }
142
+ /**
143
+ * 类目在**当前** `categories` 里的下标 —— O(1),给类目轴的 `BandScale.indexOf` 当查表口。
144
+ *
145
+ * 依据:绝对序号按「首次出现顺序」分配,而 `categories` 正是按首次出现顺序排的,
146
+ * 所以存活类目的序号是**连续的一段**(头部淘汰只让这段整体后移;万一出现空洞,
147
+ * `removeCategory` 会就地压紧)。于是「下标 = 自己的序号 − 首项序号」。
148
+ * 调用方负责把类目 `String` 化(与 `BandScale` 的查表契约一致)。
149
+ */
150
+ export declare function rawCategoryIndex(store: SeriesRawPoints, key: string): number;
122
151
  export interface InternalSeries {
123
152
  id: string;
124
153
  index: number;
@@ -247,6 +276,23 @@ export declare function toNumber(value: any): number | null;
247
276
  * 「惰性原始点」存储(`rawAccessors`)。两边必须是同一份规则 —— 否则「普通系列」与
248
277
  * 「virtual 系列」合成出来的 `xValue / y / name / size` 会分叉,提示框和命中跟着漂。
249
278
  */
279
+ export declare function readGenericPointInto(item: any, index: number, option: {
280
+ type?: string;
281
+ xField?: string;
282
+ yField?: string;
283
+ }, out: {
284
+ xValue: any;
285
+ y: number | null;
286
+ size?: number;
287
+ name?: string;
288
+ explicitX: boolean;
289
+ }): typeof out;
290
+ /**
291
+ * 取点(分配版):普通系列与列存的 `pointAt` 用。
292
+ *
293
+ * **热循环请用 `readGenericPointInto` + 复用同一个 scratch**:这个版本每次调用都会
294
+ * new 一个对象,10 万项的域重算就是每 tick 10 万个短命对象(实测过,GC 直接顶上来)。
295
+ */
250
296
  export declare function readGenericPoint(item: any, index: number, option: {
251
297
  type?: string;
252
298
  xField?: string;
@@ -294,6 +340,14 @@ export interface InternalAxis {
294
340
  index: number;
295
341
  /** y 轴位置(x 轴为 left,不使用)。 */
296
342
  position: 'left' | 'right';
343
+ /**
344
+ * 类目轴的**现成查表口**(可选):`类目 key → 下标`,O(1)。
345
+ *
346
+ * 只有「域原样来自某个增量维护的类目表、且没有被视窗裁剪」时才给得出来
347
+ * (见 `buildXDomain`)。给了它等于告诉 `BandScale`:不必自己重建索引表 ——
348
+ * 10 万类目的滚动窗口每帧重建一次那张 Map,曾是整条流水线最大的一笔。
349
+ */
350
+ categoryLookup?: (key: string) => number;
297
351
  }
298
352
  export interface NormalizedOption {
299
353
  /** 场景类型:直角坐标 / 极坐标(饼图)/ 雷达图 / 桑基图。 */
@@ -360,6 +414,16 @@ export interface AxisLayout {
360
414
  ticks: any[];
361
415
  /** 刻度标签文本。 */
362
416
  labels: string[];
417
+ /**
418
+ * **惰性格式化**:`labels[i] === ''` 且给了这个函数时,第 i 颗的文本要现算(可选)。
419
+ *
420
+ * 类目轴一个数据点一个刻度,而真正画得出来的只有抽稀后那几百颗 —— 稠密轴(> 512 颗)
421
+ * 因此只在布局那一趟格式化**量宽度用的样本**,其余留空,抽稀定稿后由
422
+ * `thinXAxisLabels` 按留下来的下标现算。数值 / 时间轴刻度本来就少,走全量那条路。
423
+ */
424
+ formatLabel?: (index: number) => string;
425
+ /** 布局那一趟按样本量到的最大标签宽度(惰性格式化时 `labels` 里只有样本,不能再抽样)。 */
426
+ sampledLabelWidth?: number;
363
427
  /** 该轴相对绘图区边缘外扩的像素距离(多轴时同侧的轴逐层外移)。 */
364
428
  offset: number;
365
429
  /** 刻度标签的最大宽度 / 高度(像素)。 */
@@ -24,6 +24,14 @@ export declare class BandScale implements Scale {
24
24
  */
25
25
  private indexCache;
26
26
  private indexCacheDomain;
27
+ /**
28
+ * 归一化交下来的**现成查表口**(可选)。
29
+ *
30
+ * 类目表是增量维护的那种轴(惰性原始点 / 滚动窗口)会带上它 —— 那时自建表等于
31
+ * 每帧重写一遍 10 万条的 Map,实测占整条流水线的一半。给了查表口就走它:
32
+ * 一个类目的下标是一次 Map 查询加一次减法。
33
+ */
34
+ private lookup;
27
35
  constructor(domain: any[], range: [number, number], options?: CreateScaleOptions);
28
36
  private computeStep;
29
37
  private indexOf;
@@ -24,6 +24,14 @@ export declare class BandScale implements Scale {
24
24
  */
25
25
  private indexCache;
26
26
  private indexCacheDomain;
27
+ /**
28
+ * 归一化交下来的**现成查表口**(可选)。
29
+ *
30
+ * 类目表是增量维护的那种轴(惰性原始点 / 滚动窗口)会带上它 —— 那时自建表等于
31
+ * 每帧重写一遍 10 万条的 Map,实测占整条流水线的一半。给了查表口就走它:
32
+ * 一个类目的下标是一次 Map 查询加一次减法。
33
+ */
34
+ private lookup;
27
35
  constructor(domain: any[], range: [number, number], options?: CreateScaleOptions);
28
36
  private computeStep;
29
37
  private indexOf;
@@ -34,5 +34,11 @@ export interface CreateScaleOptions {
34
34
  logBase?: number;
35
35
  /** 时间刻度的期望数量。 */
36
36
  tickCount?: number;
37
+ /**
38
+ * 类目轴的**现成查表口**:`类目 key → 下标`。给了它 `BandScale` 就不自建索引表。
39
+ *
40
+ * 由归一化在「域原样来自增量维护的类目表」时给出(见 `InternalAxis.categoryLookup`)。
41
+ */
42
+ categoryLookup?: (key: string) => number;
37
43
  }
38
44
  export declare function createScale(type: ScaleType, domain: any[], range: [number, number], options?: CreateScaleOptions): Scale;
@@ -34,5 +34,11 @@ export interface CreateScaleOptions {
34
34
  logBase?: number;
35
35
  /** 时间刻度的期望数量。 */
36
36
  tickCount?: number;
37
+ /**
38
+ * 类目轴的**现成查表口**:`类目 key → 下标`。给了它 `BandScale` 就不自建索引表。
39
+ *
40
+ * 由归一化在「域原样来自增量维护的类目表」时给出(见 `InternalAxis.categoryLookup`)。
41
+ */
42
+ categoryLookup?: (key: string) => number;
37
43
  }
38
44
  export declare function createScale(type: ScaleType, domain: any[], range: [number, number], options?: CreateScaleOptions): Scale;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "大漠穷秋",
3
3
  "name": "@damoqiongqiu/ice-chart",
4
- "version": "0.30.0",
4
+ "version": "0.30.2",
5
5
  "license": "MIT",
6
6
  "description": "基于 ice-render Canvas 引擎的交互式图表库:命中测试与事件派发由引擎承担,图表层只做「数据 ↔ 像素 ↔ 语义事件」。",
7
7
  "keywords": [