@cardenelabs/cdl 0.36.0 → 0.38.0
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.
- package/CHANGELOG.md +47 -1
- package/README.md +32 -9
- package/dist/index.cjs +40 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +40 -16
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +40 -16
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +40 -16
- package/dist/react.js.map +1 -1
- package/dist/{render-R7v2bfyz.d.cts → render-BYdmSviQ.d.cts} +19 -8
- package/dist/{render-R7v2bfyz.d.ts → render-BYdmSviQ.d.ts} +19 -8
- package/package.json +1 -1
- package/src/anim/core/timeline.ts +28 -10
- package/src/anim/core/types.ts +12 -0
- package/src/kinds/chart-slope.tsx +52 -8
- package/src/render/stage.tsx +17 -3
- package/src/render.tsx +8 -1
- package/src/types.ts +19 -8
|
@@ -424,18 +424,29 @@ type CdlNode = {
|
|
|
424
424
|
*/
|
|
425
425
|
chartPieForm?: ChartPieForm;
|
|
426
426
|
/**
|
|
427
|
-
* chart-slope の見せ方 (cdl#702)。
|
|
427
|
+
* chart-slope の見せ方 (cdl#702 / cdl#707)。
|
|
428
428
|
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
429
|
+
* | 値 | 縦の位置 | 左の列 | 右の列 |
|
|
430
|
+
* |---|---|---|---|
|
|
431
|
+
* | `values` | 値 | 前の値 | 今の値 |
|
|
432
|
+
* | `delta` | 値 | 前の値 | 増減 (`+40` / `-90`) |
|
|
433
|
+
* | `rank` | 順位の段 (等間隔) | 前の値 | 今の値 |
|
|
431
434
|
*
|
|
432
|
-
*
|
|
435
|
+
* `values` と `delta` は縦の位置が同じで、右の列の字だけが違う。
|
|
436
|
+
* `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
|
|
433
437
|
* 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
|
|
434
438
|
*
|
|
439
|
+
* `rank` は **縦の位置** を変える (cdl#707)。 段を等間隔に置くので、線の交差が
|
|
440
|
+
* 順位の入れ替わりと 1 対 1 になり、水平線が「順位が動かなかった」 を意味する。
|
|
441
|
+
* 字は値のままにして、量が図から消えないようにしている。
|
|
442
|
+
*
|
|
443
|
+
* `rank` では「線の傾きが動いた量」 という読み方が成立しない (`+40` と `+30` が
|
|
444
|
+
* どちらも水平線になる)。 書いた図だけに効く割り切りで、量は字を読む。
|
|
445
|
+
*
|
|
435
446
|
* 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
|
|
436
447
|
*
|
|
437
|
-
* 前の時点を持たない図 (`previous` が 1 件も無い)
|
|
438
|
-
* この欄を書いても絵は変わらない。
|
|
448
|
+
* 前の時点を持たない図 (`previous` が 1 件も無い) は軸が 1 本で並べ替える相手が
|
|
449
|
+
* いないため、 この欄を書いても絵は変わらない。
|
|
439
450
|
*/
|
|
440
451
|
chartSlopeForm?: ChartSlopeForm;
|
|
441
452
|
/**
|
|
@@ -493,8 +504,8 @@ type BoundEnum<T extends string> = T | (string & {});
|
|
|
493
504
|
/** Chart 系 kind の 1 datum payload。 label + value + optional tone (color) */
|
|
494
505
|
/** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
|
|
495
506
|
type ChartPieForm = "ring" | "arcs" | "table";
|
|
496
|
-
/** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
|
|
497
|
-
type ChartSlopeForm = "values" | "delta";
|
|
507
|
+
/** chart-slope の見せ方 (cdl#702 / cdl#707)。 SSOT は `kinds/chart-slope.tsx` */
|
|
508
|
+
type ChartSlopeForm = "values" | "delta" | "rank";
|
|
498
509
|
type ChartDatumPayload = {
|
|
499
510
|
label: string;
|
|
500
511
|
/** 棒 / 折れ線 / 扇の大きさ。 `{signal}` で状態に追随する */
|
|
@@ -424,18 +424,29 @@ type CdlNode = {
|
|
|
424
424
|
*/
|
|
425
425
|
chartPieForm?: ChartPieForm;
|
|
426
426
|
/**
|
|
427
|
-
* chart-slope の見せ方 (cdl#702)。
|
|
427
|
+
* chart-slope の見せ方 (cdl#702 / cdl#707)。
|
|
428
428
|
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
429
|
+
* | 値 | 縦の位置 | 左の列 | 右の列 |
|
|
430
|
+
* |---|---|---|---|
|
|
431
|
+
* | `values` | 値 | 前の値 | 今の値 |
|
|
432
|
+
* | `delta` | 値 | 前の値 | 増減 (`+40` / `-90`) |
|
|
433
|
+
* | `rank` | 順位の段 (等間隔) | 前の値 | 今の値 |
|
|
431
434
|
*
|
|
432
|
-
*
|
|
435
|
+
* `values` と `delta` は縦の位置が同じで、右の列の字だけが違う。
|
|
436
|
+
* `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
|
|
433
437
|
* 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
|
|
434
438
|
*
|
|
439
|
+
* `rank` は **縦の位置** を変える (cdl#707)。 段を等間隔に置くので、線の交差が
|
|
440
|
+
* 順位の入れ替わりと 1 対 1 になり、水平線が「順位が動かなかった」 を意味する。
|
|
441
|
+
* 字は値のままにして、量が図から消えないようにしている。
|
|
442
|
+
*
|
|
443
|
+
* `rank` では「線の傾きが動いた量」 という読み方が成立しない (`+40` と `+30` が
|
|
444
|
+
* どちらも水平線になる)。 書いた図だけに効く割り切りで、量は字を読む。
|
|
445
|
+
*
|
|
435
446
|
* 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
|
|
436
447
|
*
|
|
437
|
-
* 前の時点を持たない図 (`previous` が 1 件も無い)
|
|
438
|
-
* この欄を書いても絵は変わらない。
|
|
448
|
+
* 前の時点を持たない図 (`previous` が 1 件も無い) は軸が 1 本で並べ替える相手が
|
|
449
|
+
* いないため、 この欄を書いても絵は変わらない。
|
|
439
450
|
*/
|
|
440
451
|
chartSlopeForm?: ChartSlopeForm;
|
|
441
452
|
/**
|
|
@@ -493,8 +504,8 @@ type BoundEnum<T extends string> = T | (string & {});
|
|
|
493
504
|
/** Chart 系 kind の 1 datum payload。 label + value + optional tone (color) */
|
|
494
505
|
/** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
|
|
495
506
|
type ChartPieForm = "ring" | "arcs" | "table";
|
|
496
|
-
/** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
|
|
497
|
-
type ChartSlopeForm = "values" | "delta";
|
|
507
|
+
/** chart-slope の見せ方 (cdl#702 / cdl#707)。 SSOT は `kinds/chart-slope.tsx` */
|
|
508
|
+
type ChartSlopeForm = "values" | "delta" | "rank";
|
|
498
509
|
type ChartDatumPayload = {
|
|
499
510
|
label: string;
|
|
500
511
|
/** 棒 / 折れ線 / 扇の大きさ。 `{signal}` で状態に追随する */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
|
@@ -60,6 +60,8 @@ export class Timeline {
|
|
|
60
60
|
private rafHandle: number | null = null;
|
|
61
61
|
private phaseIndex = 0;
|
|
62
62
|
private phaseProgress = 0;
|
|
63
|
+
/** 曲線を通す前の進み (cdl#711)。 経過時間そのものの割合で、 描く動きが読む */
|
|
64
|
+
private phaseLinearProgress = 0;
|
|
63
65
|
private phaseStartedAt = 0;
|
|
64
66
|
private status: TimelineStatus = "idle";
|
|
65
67
|
/**
|
|
@@ -75,7 +77,7 @@ export class Timeline {
|
|
|
75
77
|
*/
|
|
76
78
|
private readonly initialState: {
|
|
77
79
|
phaseIndex: number;
|
|
78
|
-
|
|
80
|
+
phaseLinearProgress: number;
|
|
79
81
|
status: TimelineStatus;
|
|
80
82
|
};
|
|
81
83
|
|
|
@@ -94,12 +96,12 @@ export class Timeline {
|
|
|
94
96
|
const initial = options.initialPhaseIndex;
|
|
95
97
|
if (initial != null && initial > 0 && initial < phases.length) {
|
|
96
98
|
this.phaseIndex = initial;
|
|
97
|
-
this.
|
|
99
|
+
this.setProgress(1);
|
|
98
100
|
this.status = initial === phases.length - 1 ? "settled" : "paused";
|
|
99
101
|
}
|
|
100
102
|
this.initialState = {
|
|
101
103
|
phaseIndex: this.phaseIndex,
|
|
102
|
-
|
|
104
|
+
phaseLinearProgress: this.phaseLinearProgress,
|
|
103
105
|
status: this.status,
|
|
104
106
|
};
|
|
105
107
|
}
|
|
@@ -133,6 +135,7 @@ export class Timeline {
|
|
|
133
135
|
cached.status === this.status &&
|
|
134
136
|
cached.phaseIndex === this.phaseIndex &&
|
|
135
137
|
cached.phaseProgress === this.phaseProgress &&
|
|
138
|
+
cached.phaseLinearProgress === this.phaseLinearProgress &&
|
|
136
139
|
cached.totalPhases === this.phases.length
|
|
137
140
|
) {
|
|
138
141
|
return cached;
|
|
@@ -141,6 +144,7 @@ export class Timeline {
|
|
|
141
144
|
status: this.status,
|
|
142
145
|
phaseIndex: this.phaseIndex,
|
|
143
146
|
phaseProgress: this.phaseProgress,
|
|
147
|
+
phaseLinearProgress: this.phaseLinearProgress,
|
|
144
148
|
totalPhases: this.phases.length,
|
|
145
149
|
};
|
|
146
150
|
this.cachedSnapshot = next;
|
|
@@ -168,7 +172,7 @@ export class Timeline {
|
|
|
168
172
|
const clamped = Math.max(0, Math.min(this.phases.length - 1, index));
|
|
169
173
|
this.cancelRaf();
|
|
170
174
|
this.phaseIndex = clamped;
|
|
171
|
-
this.
|
|
175
|
+
this.setProgress(1);
|
|
172
176
|
this.status = clamped === this.phases.length - 1 ? "settled" : "paused";
|
|
173
177
|
this.emit();
|
|
174
178
|
}
|
|
@@ -212,7 +216,7 @@ export class Timeline {
|
|
|
212
216
|
if (this.phaseIndex <= 0) return;
|
|
213
217
|
this.cancelRaf();
|
|
214
218
|
this.phaseIndex -= 1;
|
|
215
|
-
this.
|
|
219
|
+
this.setProgress(1);
|
|
216
220
|
this.status = "paused";
|
|
217
221
|
this.emit();
|
|
218
222
|
}
|
|
@@ -220,7 +224,7 @@ export class Timeline {
|
|
|
220
224
|
reset(): void {
|
|
221
225
|
this.cancelRaf();
|
|
222
226
|
this.phaseIndex = 0;
|
|
223
|
-
this.
|
|
227
|
+
this.setProgress(0);
|
|
224
228
|
this.status = "idle";
|
|
225
229
|
this.emit();
|
|
226
230
|
}
|
|
@@ -242,7 +246,7 @@ export class Timeline {
|
|
|
242
246
|
this.subscribers.clear();
|
|
243
247
|
this.status = this.initialState.status;
|
|
244
248
|
this.phaseIndex = this.initialState.phaseIndex;
|
|
245
|
-
this.
|
|
249
|
+
this.setProgress(this.initialState.phaseLinearProgress);
|
|
246
250
|
}
|
|
247
251
|
|
|
248
252
|
// ─── internals ───────────────────────────────────────────────
|
|
@@ -284,7 +288,7 @@ export class Timeline {
|
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
private beginPhaseTransition(): void {
|
|
287
|
-
this.
|
|
291
|
+
this.setProgress(0);
|
|
288
292
|
this.phaseStartedAt = performance.now();
|
|
289
293
|
this.cancelRaf();
|
|
290
294
|
const step = (now: number) => {
|
|
@@ -292,13 +296,13 @@ export class Timeline {
|
|
|
292
296
|
this.autoAdvanceMsOverride ?? this.getPhase().durationMs ?? 600;
|
|
293
297
|
const elapsed = now - this.phaseStartedAt;
|
|
294
298
|
const linearT = clamp01(elapsed / duration);
|
|
295
|
-
this.
|
|
299
|
+
this.setProgress(linearT);
|
|
296
300
|
this.emit();
|
|
297
301
|
if (linearT < 1) {
|
|
298
302
|
this.rafHandle = requestAnimationFrame(step);
|
|
299
303
|
return;
|
|
300
304
|
}
|
|
301
|
-
this.
|
|
305
|
+
this.setProgress(1);
|
|
302
306
|
this.emit();
|
|
303
307
|
if (this.status === "playing") {
|
|
304
308
|
// 自動進行中は次 Phase へ
|
|
@@ -315,6 +319,20 @@ export class Timeline {
|
|
|
315
319
|
this.rafHandle = requestAnimationFrame(step);
|
|
316
320
|
}
|
|
317
321
|
|
|
322
|
+
/**
|
|
323
|
+
* 段の進みを 2 つ同時に置く (cdl#711)。
|
|
324
|
+
*
|
|
325
|
+
* **代入する場所を 1 つに閉じる**。 曲げた進みと曲げる前の進みを別々に書くと、
|
|
326
|
+
* どちらかを更新し忘れた経路が「前の段の値のまま」 で残る。
|
|
327
|
+
*
|
|
328
|
+
* 両端 (0 と 1) は曲線を通さず、 そのまま置く。 曲線は差し替えられる欄なので、
|
|
329
|
+
* `easing(1)` が 1 を返す保証がない。 段の始まりと終わりの値は曲線に委ねない。
|
|
330
|
+
*/
|
|
331
|
+
private setProgress(linear: number): void {
|
|
332
|
+
this.phaseLinearProgress = linear;
|
|
333
|
+
this.phaseProgress = linear <= 0 ? 0 : linear >= 1 ? 1 : this.easing(linear);
|
|
334
|
+
}
|
|
335
|
+
|
|
318
336
|
private cancelRaf(): void {
|
|
319
337
|
if (this.rafHandle != null) {
|
|
320
338
|
cancelAnimationFrame(this.rafHandle);
|
package/src/anim/core/types.ts
CHANGED
|
@@ -37,6 +37,18 @@ export type TimelineState = {
|
|
|
37
37
|
phaseIndex: number;
|
|
38
38
|
/** 現在 Phase 内の進行度 (0..1)、 視覚要素の補間に使う */
|
|
39
39
|
phaseProgress: number;
|
|
40
|
+
/**
|
|
41
|
+
* 曲線を通す前の進行度 (0..1、 cdl#711)。 経過時間そのものの割合。
|
|
42
|
+
*
|
|
43
|
+
* `phaseProgress` は既定で `easeOutQuint` を通るため前半に動きが寄る。
|
|
44
|
+
* **値が落ち着く動きには合うが、 線を引く動きには合わない** =
|
|
45
|
+
* `1.2s` の段で半分に達するのが 158 ms になり、 折れ線の 5 点のうち 4 点が
|
|
46
|
+
* 292 ms の間に出てしまう (実測)。
|
|
47
|
+
*
|
|
48
|
+
* 描く動き (`draw` の node と伸ばす edge) はこちらを読む。
|
|
49
|
+
* 両端 (0 と 1) は 2 つとも同じ値になる。
|
|
50
|
+
*/
|
|
51
|
+
phaseLinearProgress: number;
|
|
40
52
|
/** 全 Phase 数 */
|
|
41
53
|
totalPhases: number;
|
|
42
54
|
};
|
|
@@ -50,6 +50,24 @@ import { 進みを畳む, 伸ばすdash } from "./draw-progress";
|
|
|
50
50
|
*
|
|
51
51
|
* 色を持たせるのは **名前だけ**。 値は太字の濃い色のままにして、数の読み比べを保つ。
|
|
52
52
|
* identity は色が、量は字が担う。
|
|
53
|
+
*
|
|
54
|
+
* ## 順位で見せる形は縦の位置を変える (cdl#707)
|
|
55
|
+
*
|
|
56
|
+
* この図は「線の交差が順位の入れ替わり」 を読ませるが、縦の位置は値なので **交差点の
|
|
57
|
+
* 位置が順位と噛み合わない**。 どの交差が本当に順位を変えた交差なのかは、値を読み比べ
|
|
58
|
+
* ないと決まらない。
|
|
59
|
+
*
|
|
60
|
+
* `rank` は段を等間隔に置く。 交差が入れ替わりと 1 対 1 になり、水平線が「順位が
|
|
61
|
+
* 動かなかった」 を意味する。
|
|
62
|
+
*
|
|
63
|
+
* **字は値のままにする**。 字も順位にすると `380 → 420` と `60 → 90` がどちらも
|
|
64
|
+
* 同じ水平線になり、量が図から完全に消える。 位置が順位を、字が量を担う。
|
|
65
|
+
*
|
|
66
|
+
* 順位と値を **両方** 出す案は落とした = 3 つ目の数を足す形で、実物に当てると値の列が
|
|
67
|
+
* 伸びて名前と重なった (`delta` で落としたのと同じ形、cdl#702)。
|
|
68
|
+
*
|
|
69
|
+
* **この形では「線の傾きが動いた量」 が成立しない**。 `+40` と `+30` がどちらも水平線に
|
|
70
|
+
* なる。 書いた図だけに効く割り切りで、量は字を読む。
|
|
53
71
|
*/
|
|
54
72
|
|
|
55
73
|
/** 線を引くのに最低限要る横幅。 名札が長い図でもこれだけは残す */
|
|
@@ -113,14 +131,39 @@ export function ChartSlopeNode({
|
|
|
113
131
|
尺の幅 > 0 ? 下端 - ((v - 最小) / 尺の幅) * (下端 - 上端) : (上端 + 下端) / 2;
|
|
114
132
|
|
|
115
133
|
/**
|
|
116
|
-
* 見せ方 (cdl#702)。 **型の外の値は `values` に落とす** =
|
|
117
|
-
*
|
|
134
|
+
* 見せ方 (cdl#702 / cdl#707)。 **型の外の値は `values` に落とす** = 見せ方が
|
|
135
|
+
* 決まらないより、既定の形が出る方がよい (円グラフと同じ判断)。
|
|
136
|
+
*
|
|
137
|
+
* **前の時点を持たない図では `values` に落とす**。 `delta` は引く相手がいないので、
|
|
138
|
+
* 増減を出すと「0 から増えた」 という書いていない主張になる (前を持たない件を 0 から
|
|
139
|
+
* 立ち上げるのは線を引くための扱いで、前が 0 だったという意味ではない)。
|
|
140
|
+
* `rank` は軸が 1 本で並べ替える相手がいない。
|
|
141
|
+
*/
|
|
142
|
+
const 書いた形 = node.chartSlopeForm;
|
|
143
|
+
const 形: ChartSlopeForm =
|
|
144
|
+
前あり && (書いた形 === "delta" || 書いた形 === "rank") ? 書いた形 : "values";
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 順位。 **自分より大きい値の件数 + 1** で決める。
|
|
148
|
+
*
|
|
149
|
+
* 同じ値なら同じ順位になり、段も重なる。 無理に 1 つずつずらすと、書いていない差を
|
|
150
|
+
* 絵が主張することになる。
|
|
151
|
+
*/
|
|
152
|
+
const 順位を取る = (v: number, 全部: number[]): number =>
|
|
153
|
+
全部.filter((x) => x > v).length + 1;
|
|
154
|
+
|
|
155
|
+
const 前の順位 = 系列たち.map((s) => 順位を取る(s.前, 系列たち.map((x) => x.前)));
|
|
156
|
+
const 今の順位 = 系列たち.map((s) => 順位を取る(s.今, 系列たち.map((x) => x.今)));
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 段の y。 1 位を上端、系列の数を下端にして等間隔に置く。
|
|
118
160
|
*
|
|
119
|
-
*
|
|
120
|
-
* 「0 から増えた」 という書いていない主張になる (前を持たない件を 0 から立ち上げるのは
|
|
121
|
-
* 線を引くための扱いで、前が 0 だったという意味ではない)。
|
|
161
|
+
* **系列が 1 本の図では割り算ができない**ので縦の中央に置く (尺の幅が 0 の時と同じ扱い)。
|
|
122
162
|
*/
|
|
123
|
-
const
|
|
163
|
+
const 段のyを取る = (順位: number): number =>
|
|
164
|
+
系列たち.length > 1
|
|
165
|
+
? 上端 + ((順位 - 1) / (系列たち.length - 1)) * (下端 - 上端)
|
|
166
|
+
: (上端 + 下端) / 2;
|
|
124
167
|
|
|
125
168
|
/**
|
|
126
169
|
* 増減の表記。 符号を前に付ける。
|
|
@@ -233,8 +276,9 @@ export function ChartSlopeNode({
|
|
|
233
276
|
)}
|
|
234
277
|
|
|
235
278
|
{系列たち.map((s, i) => {
|
|
236
|
-
|
|
237
|
-
const
|
|
279
|
+
// `rank` は縦の位置を順位の段にする (cdl#707)。 値の尺は使わない
|
|
280
|
+
const 左y = 形 === "rank" ? 段のyを取る(前の順位[i]!) : yを取る(s.前);
|
|
281
|
+
const 右y = 形 === "rank" ? 段のyを取る(今の順位[i]!) : yを取る(s.今);
|
|
238
282
|
const 未解決 = s.未解決 ? "true" : undefined;
|
|
239
283
|
return (
|
|
240
284
|
<g key={`slope-${i}`}>
|
package/src/render/stage.tsx
CHANGED
|
@@ -28,6 +28,7 @@ export function CdlStage({
|
|
|
28
28
|
laid,
|
|
29
29
|
currentPhase,
|
|
30
30
|
progress,
|
|
31
|
+
drawProgress,
|
|
31
32
|
stateValues,
|
|
32
33
|
debug,
|
|
33
34
|
compact = false,
|
|
@@ -36,6 +37,13 @@ export function CdlStage({
|
|
|
36
37
|
laid: LaidDiagram;
|
|
37
38
|
currentPhase: CdlPhase | undefined;
|
|
38
39
|
progress: number;
|
|
40
|
+
/**
|
|
41
|
+
* 描く動きが読む進み (cdl#711)。 曲線を通す前の値で、 経過時間そのものの割合。
|
|
42
|
+
*
|
|
43
|
+
* 書かない呼出は `progress` と同じ値になる = 曲線を通した進みで描く従来の形。
|
|
44
|
+
* 検査から直接呼ぶ経路が既に多数あり、 そこでは 2 つを分ける意味がない。
|
|
45
|
+
*/
|
|
46
|
+
drawProgress?: number;
|
|
39
47
|
stateValues: Record<string, string>;
|
|
40
48
|
debug: boolean;
|
|
41
49
|
compact?: boolean;
|
|
@@ -112,9 +120,15 @@ export function CdlStage({
|
|
|
112
120
|
}
|
|
113
121
|
return scales;
|
|
114
122
|
}, [laid]);
|
|
115
|
-
|
|
123
|
+
/**
|
|
124
|
+
* 描く動きの素の進み (cdl#711)。 渡されなければ従来どおり曲線を通した進みを使う。
|
|
125
|
+
*
|
|
126
|
+
* **`??` で受ける** = 0 は正しい進み (段の始まり) なので、 偽としては落とせない。
|
|
127
|
+
*/
|
|
128
|
+
const 描く素の進み = drawProgress ?? progress;
|
|
129
|
+
// 描く対象から見た進み (cdl#570)。 `drawRatio` を書かない phase では `描く素の進み` と同値で、
|
|
116
130
|
// 描く速さを phase の長さから切り離すためだけに使う
|
|
117
|
-
const 描く進み = 描く進みに直す(
|
|
131
|
+
const 描く進み = 描く進みに直す(描く素の進み, currentPhase?.drawRatio);
|
|
118
132
|
// 縦線の終点は全 lane で 1 つに揃える (等長保証)。 値の決め方と、 1 lane の異常が図全体から
|
|
119
133
|
// 縦線を消していた形の対処は `uniformLifelineEndY` の説明。
|
|
120
134
|
//
|
|
@@ -345,7 +359,7 @@ export function CdlStage({
|
|
|
345
359
|
edge={edge}
|
|
346
360
|
active={activeSet.has(edge.id)}
|
|
347
361
|
drawing={矢印の出番.伸ばすか(edge.id)}
|
|
348
|
-
progress={progress}
|
|
362
|
+
progress={矢印の出番.伸ばすか(edge.id) ? 描く進み : progress}
|
|
349
363
|
stateValues={stateValues}
|
|
350
364
|
/>
|
|
351
365
|
))}
|
package/src/render.tsx
CHANGED
|
@@ -133,6 +133,13 @@ export function CdlDiagramView({ diagram, laid: laidProp, hideHeader = false, hi
|
|
|
133
133
|
: state.phaseIndex;
|
|
134
134
|
const currentPhase = laid.phases[Math.max(0, phaseIdx)] ?? laid.phases[0];
|
|
135
135
|
const progress = reduced ? 1 : state.phaseProgress;
|
|
136
|
+
/**
|
|
137
|
+
* 描く動きが読む進み (cdl#711)。 曲線を通さない = 経過時間そのものの割合。
|
|
138
|
+
*
|
|
139
|
+
* 線を引く動きに `easeOutQuint` を当てると前半に寄り、 折れ線の 5 点のうち 4 点が
|
|
140
|
+
* 292 ms の間に出る。 ペンの速さは一定であるほど「1 つずつ現れる」 が読める。
|
|
141
|
+
*/
|
|
142
|
+
const drawProgress = reduced ? 1 : state.phaseLinearProgress;
|
|
136
143
|
|
|
137
144
|
// state 値を計算 (現在 phase + これまでの phase の最終 tween 値を集約)
|
|
138
145
|
const baseStateValues = computeStateValues(laid, phaseIdx, progress);
|
|
@@ -184,7 +191,7 @@ export function CdlDiagramView({ diagram, laid: laidProp, hideHeader = false, hi
|
|
|
184
191
|
{/* interactive panel = input widget / formula readout / scroll readout (SVG の上に配置)、
|
|
185
192
|
diagram に interactive primitive がなければ null (SSR / render 影響なし) */}
|
|
186
193
|
{isInteractive && interactive.panel}
|
|
187
|
-
<CdlStage laid={laid} currentPhase={currentPhase} progress={progress} stateValues={stateValues} debug={debug} compact={hideHeader} svgRef={isInteractive ? interactive.svgRef : undefined} />
|
|
194
|
+
<CdlStage laid={laid} currentPhase={currentPhase} progress={progress} drawProgress={drawProgress} stateValues={stateValues} debug={debug} compact={hideHeader} svgRef={isInteractive ? interactive.svgRef : undefined} />
|
|
188
195
|
{/* hideHeader + multi-phase 時、 phase indicator が消えると動きが読めないため
|
|
189
196
|
mini indicator (dot 列 + 現在 phase title + badge) を bottom に追加 */}
|
|
190
197
|
{hideHeader && !hideMiniPhaseIndicator && currentPhase && laid.phases.length > 1 && (
|
package/src/types.ts
CHANGED
|
@@ -483,18 +483,29 @@ export type CdlNode = {
|
|
|
483
483
|
*/
|
|
484
484
|
chartPieForm?: ChartPieForm;
|
|
485
485
|
/**
|
|
486
|
-
* chart-slope の見せ方 (cdl#702)。
|
|
486
|
+
* chart-slope の見せ方 (cdl#702 / cdl#707)。
|
|
487
487
|
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
488
|
+
* | 値 | 縦の位置 | 左の列 | 右の列 |
|
|
489
|
+
* |---|---|---|---|
|
|
490
|
+
* | `values` | 値 | 前の値 | 今の値 |
|
|
491
|
+
* | `delta` | 値 | 前の値 | 増減 (`+40` / `-90`) |
|
|
492
|
+
* | `rank` | 順位の段 (等間隔) | 前の値 | 今の値 |
|
|
490
493
|
*
|
|
491
|
-
*
|
|
494
|
+
* `values` と `delta` は縦の位置が同じで、右の列の字だけが違う。
|
|
495
|
+
* `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
|
|
492
496
|
* 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
|
|
493
497
|
*
|
|
498
|
+
* `rank` は **縦の位置** を変える (cdl#707)。 段を等間隔に置くので、線の交差が
|
|
499
|
+
* 順位の入れ替わりと 1 対 1 になり、水平線が「順位が動かなかった」 を意味する。
|
|
500
|
+
* 字は値のままにして、量が図から消えないようにしている。
|
|
501
|
+
*
|
|
502
|
+
* `rank` では「線の傾きが動いた量」 という読み方が成立しない (`+40` と `+30` が
|
|
503
|
+
* どちらも水平線になる)。 書いた図だけに効く割り切りで、量は字を読む。
|
|
504
|
+
*
|
|
494
505
|
* 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
|
|
495
506
|
*
|
|
496
|
-
* 前の時点を持たない図 (`previous` が 1 件も無い)
|
|
497
|
-
* この欄を書いても絵は変わらない。
|
|
507
|
+
* 前の時点を持たない図 (`previous` が 1 件も無い) は軸が 1 本で並べ替える相手が
|
|
508
|
+
* いないため、 この欄を書いても絵は変わらない。
|
|
498
509
|
*/
|
|
499
510
|
chartSlopeForm?: ChartSlopeForm;
|
|
500
511
|
/**
|
|
@@ -556,8 +567,8 @@ export type BoundEnum<T extends string> = T | (string & {});
|
|
|
556
567
|
/** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
|
|
557
568
|
export type ChartPieForm = "ring" | "arcs" | "table";
|
|
558
569
|
|
|
559
|
-
/** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
|
|
560
|
-
export type ChartSlopeForm = "values" | "delta";
|
|
570
|
+
/** chart-slope の見せ方 (cdl#702 / cdl#707)。 SSOT は `kinds/chart-slope.tsx` */
|
|
571
|
+
export type ChartSlopeForm = "values" | "delta" | "rank";
|
|
561
572
|
|
|
562
573
|
export type ChartDatumPayload = {
|
|
563
574
|
label: string;
|