1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Band = void 0;
|
4 | const ordinal_1 = require("./ordinal");
|
5 | const sequence_1 = require("../utils/sequence");
|
6 | /**
|
7 | * 基于 band 基础配置获取 band 的状态
|
8 | *
|
9 | * @param opt 相关选项
|
10 | * @see BandStateOptions
|
11 | * @return {object} 一个新对象, 包含以下内容:
|
12 | * step -- 步长
|
13 | * adjustedRange -- 最终得到的 range
|
14 | * bandWidth -- band 宽度
|
15 | */
|
16 | function getBandState(opt) {
|
17 | const DEFAULT_OPTIONS = {
|
18 | range: [0, 1],
|
19 | align: 0.5,
|
20 | round: false,
|
21 | paddingInner: 0,
|
22 | paddingOuter: 0,
|
23 | };
|
24 | const option = {
|
25 | ...DEFAULT_OPTIONS,
|
26 | ...opt,
|
27 | };
|
28 | const { range, stepAmount, paddingOuter, paddingInner } = option;
|
29 | let step;
|
30 | let bandWidth;
|
31 | let rangeStart = range[0];
|
32 | const rangeEnd = range[1];
|
33 | // range 的计算方式如下:
|
34 | // = stop - start
|
35 | // = (stepAmount * step(n 个 step) )
|
36 | // + (2 * step * paddingOuter(两边的 padding))
|
37 | // - (1 * step * paddingInner(多出的一个 inner))
|
38 | const deltaRange = rangeEnd - rangeStart;
|
39 | const outerTotal = paddingOuter * 2;
|
40 | const innerTotal = stepAmount - paddingInner;
|
41 | step = deltaRange / Math.max(1, outerTotal + innerTotal);
|
42 | // 优化成整数
|
43 | if (option.round) {
|
44 | step = Math.floor(step);
|
45 | }
|
46 | // 基于 align 实现偏移
|
47 | rangeStart += (deltaRange - step * (stepAmount - paddingInner)) * option.align;
|
48 | // 一个 step 的组成如下:
|
49 | // step = bandWidth + step * paddingInner,
|
50 | // 则 bandWidth = step - step * (paddingInner)
|
51 | bandWidth = step * (1 - paddingInner);
|
52 | if (option.round) {
|
53 | rangeStart = Math.round(rangeStart);
|
54 | bandWidth = Math.round(bandWidth);
|
55 | }
|
56 | // 转化后的 range
|
57 | const adjustedRange = sequence_1.sequence(rangeStart, rangeEnd, step);
|
58 | return {
|
59 | step,
|
60 | adjustedRange,
|
61 | bandWidth,
|
62 | };
|
63 | }
|
64 | /**
|
65 | * Band 比例尺
|
66 | *
|
67 | * 一种特殊的 ordinal scale,区别在于值域的范围是连续的。
|
68 | * 使用的场景例如柱状图,可以用来定位各个柱子水平方向距离原点开始绘制的距离、各柱子之间的间距
|
69 | *
|
70 | * 由于部分选项较为抽象,见下图描述:
|
71 | *
|
72 | * PO = paddingOuter
|
73 | * PI = paddingInner
|
74 | *
|
75 | * domain = [A, B]
|
76 | *
|
77 | * |<------------------------------------------- range ------------------------------------------->|
|
78 | * | | | | | | |
|
79 | * |<--step*PO-->|<----bandWidth---->|<--step*PI-->|<----bandWidth---->|<--step*PI-->|<--step*PO-->|
|
80 | * | | ***************** | | ***************** | | |
|
81 | * | | ******* A ******* | | ******* B ******* | | |
|
82 | * | | ***************** | | ***************** | | |
|
83 | * | |<--------------step------------->| |
|
84 | * |-----------------------------------------------------------------------------------------------|
|
85 | *
|
86 | * 性能方便较 d3 快出 8 - 9 倍
|
87 | */
|
88 | class Band extends ordinal_1.Ordinal {
|
89 | // 显示指定 options 的类型为 OrdinalOptions,从而推断出 O 的类型
|
90 | constructor(options) {
|
91 | super(options);
|
92 | }
|
93 | // 覆盖默认配置
|
94 | getDefaultOptions() {
|
95 | return {
|
96 | domain: [],
|
97 | range: [0, 1],
|
98 | align: 0.5,
|
99 | round: false,
|
100 | paddingInner: 0,
|
101 | paddingOuter: 0,
|
102 | padding: 0,
|
103 | unknown: undefined,
|
104 | };
|
105 | }
|
106 | clone() {
|
107 | return new Band(this.options);
|
108 | }
|
109 | getStep() {
|
110 | return this.step;
|
111 | }
|
112 | getBandWidth() {
|
113 | return this.bandWidth;
|
114 | }
|
115 | getRange() {
|
116 | return this.adjustedRange;
|
117 | }
|
118 | getPaddingInner() {
|
119 | const { padding, paddingInner } = this.options;
|
120 | return padding > 0 ? padding : paddingInner;
|
121 | }
|
122 | getPaddingOuter() {
|
123 | const { padding, paddingOuter } = this.options;
|
124 | return padding > 0 ? padding : paddingOuter;
|
125 | }
|
126 | rescale() {
|
127 | super.rescale();
|
128 | // 当用户配置了opt.padding 且非 0 时,我们覆盖已经设置的 paddingInner paddingOuter
|
129 | // 我们约定 padding 的优先级较 paddingInner 和 paddingOuter 高
|
130 | const { align, domain, range, round } = this.options;
|
131 | const { step, bandWidth, adjustedRange } = getBandState({
|
132 | align,
|
133 | range,
|
134 | round,
|
135 | paddingInner: this.getPaddingInner(),
|
136 | paddingOuter: this.getPaddingOuter(),
|
137 | stepAmount: domain.length,
|
138 | });
|
139 | // 更新必要的属性
|
140 | this.step = step;
|
141 | this.bandWidth = bandWidth;
|
142 | this.adjustedRange = adjustedRange;
|
143 | }
|
144 | }
|
145 | exports.Band = Band;
|
146 | //# sourceMappingURL=band.js.map |
\ | No newline at end of file |