UNPKG

4.94 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Band = void 0;
4const ordinal_1 = require("./ordinal");
5const 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 */
16function 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 */
88class 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}
145exports.Band = Band;
146//# sourceMappingURL=band.js.map
\No newline at end of file