Skip to content

Commit 1a411ef

Browse files
committed
feat: optimize the maximum value logic and update the documentation
1 parent dcb8df6 commit 1a411ef

3 files changed

Lines changed: 63 additions & 14 deletions

File tree

__tests__/unit/scales/linear-breaks.spec.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,8 @@ describe('Linear Scale with Breaks', () => {
6060
});
6161

6262
const { domain, range } = scale.getOptions();
63-
expect(domain).toStrictEqual([0, 200, 300, 500, 600, 800, 980]);
64-
expect(range).toStrictEqual([
65-
0, 0.20408163265306123, 0.35816326530612247, 0.45816326530612245, 0.6892857142857143, 0.7392857142857143, 1,
66-
]);
63+
expect(domain).toStrictEqual([0, 200, 300, 500, 600, 800, 1000]);
64+
expect(range).toStrictEqual([0, 0.2, 0.35000000000000003, 0.45, 0.6749999999999999, 0.725, 1]);
6765
});
6866

6967
test('single break: update', () => {
@@ -109,17 +107,18 @@ describe('Linear Scale with Breaks', () => {
109107
expect(scale2).toBeInstanceOf(Linear);
110108
expect(scale2.getOptions()).toEqual(scale.getOptions());
111109
});
112-
test('breaks with nice', () => {
110+
test.only('breaks with nice', () => {
113111
const scale = new Linear({
114112
domain: [0, 3106679],
115113
breaks: [{ start: 5000, end: 50000, gap: 0.03 }],
116114
});
117115

118116
const { domain, range } = scale.getOptions();
119-
expect(domain).toStrictEqual([0, 5000, 50000, 1000000, 1500000, 2000000, 2500000, 3000000, 3106679]);
117+
expect(domain).toStrictEqual([0, 5000, 50000, 1000000, 1500000, 2000000, 2500000, 3000000, 3150000]);
118+
120119
expect(range).toStrictEqual([
121-
1, 0.8, 0.7700000000000001, 0.6781128658609403, 0.5171692987914104, 0.35622573172188055, 0.1952821646523506,
122-
0.03433859758282076, 0,
120+
1, 0.8, 0.7700000000000001, 0.6825396825396826, 0.5238095238095238, 0.3650793650793651, 0.2063492063492064,
121+
0.04761904761904767, 0,
123122
]);
124123
scale.update({
125124
domain: [0, 3106679],
@@ -145,9 +144,8 @@ describe('Linear Scale with Breaks', () => {
145144
],
146145
});
147146
const scaleOptions2 = scale.getOptions();
148-
expect(scaleOptions2.domain).toStrictEqual([0, 5000, 50000, 105000, 3100000, 3106679]);
149-
expect(scaleOptions2.range).toStrictEqual([
150-
1, 0.8, 0.7700000000000001, 0.49917586754215676, 0.46917586754215673, 0,
151-
]);
147+
expect(scaleOptions2.domain).toStrictEqual([0, 5000, 50000, 105000, 3100000, 3108000]);
148+
149+
expect(scaleOptions2.range).toStrictEqual([1, 0.8, 0.7700000000000001, 0.4993951093951094, 0.46939510939510937, 0]);
152150
});
153151
});

docs/api/scales/linear.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,45 @@ x2.getTicks(); // [0, 2.5, 5, 7.5, 10, 12.5, 15, 17.5]
162162
x3.getTicks(); // [2, 4.5, 7, 9.5, 12, 14.5]
163163
```
164164

165+
- Breaks
166+
167+
```ts
168+
import { Linear, LinearOptions } from '@antv/scale';
169+
170+
const options1: LinearOptions = {
171+
domain: [0, 3106679],
172+
breaks: [{ start: 5000, end: 50000, gap: 0.03 }],
173+
};
174+
175+
const x1 = new Linear(options1);
176+
177+
x1.getTicks(); // [0, 5000, 50000, 1000000, 1500000, 2000000, 2500000, 3000000, 3150000]
178+
179+
// with nice
180+
const options2: LinearOptions = {
181+
domain: [0, 3106679],
182+
nice: true,
183+
breaks: [{ start: 5000, end: 50000, gap: 0.03 }],
184+
};
185+
186+
const x2 = new Linear(options2);
187+
188+
x2.getTicks(); // [0, 5000, 50000, 1000000, 1500000, 2000000, 2500000, 3000000, 3500000]
189+
190+
// multi breaks
191+
const options3:LinearOptions = {
192+
domain: [0, 200],
193+
breaks: [
194+
{ start: 40, end: 100, gap: 0.1 },
195+
{ start: 120, end: 160, gap: 0.1 },
196+
]
197+
}
198+
199+
const x3 = new Linear(options3);
200+
201+
x3.getTicks(); // [0, 40, 100, 120, 160, 200]
202+
```
203+
165204
## Options
166205

167206
| Key | Description | Type | Default|
@@ -175,6 +214,15 @@ x3.getTicks(); // [2, 4.5, 7, 9.5, 12, 14.5]
175214
| clamp | Constrains the return value of map within the scale’s range if it is true. | `boolean` | `false` |
176215
| nice | Extends the domain so that it starts and ends on nice round values if it is true. | `boolean` | `false` |
177216
| interpolate | Sets the scale’s range interpolator factory if it is specified. | `(a: number, b: number) => (t: number) => T` | `(a, b) => (t) => a * (1 - t) + b * t` |
217+
| breaks | Set linear breaks display and style. | [breaks](#breaks) | - |
218+
219+
### breaks
220+
221+
| Key | Description | Type | Default Value |
222+
| ------- | ------- | ------- | ------- |
223+
| start | start value. | `number` | - |
224+
| end |end value. | `number` | - |
225+
| gap | Proportion of the broken (0 ~ 1). | `number` | 0.03 |
178226

179227
## Methods
180228

src/scales/linear.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { LinearOptions, Transform } from '../types';
44
import { Base } from './base';
55
import { createInterpolateValue } from '../utils';
66
import { d3Ticks } from '../tick-methods/d3-ticks';
7+
import { d3LinearNice } from '../utils/d3-linear-nice';
78

89
/**
910
* Linear 比例尺
@@ -68,11 +69,13 @@ export class Linear extends Continuous<LinearOptions> {
6869
niceDomainMax = niceDomain[niceDomain.length - 1];
6970
}
7071
const domainMin = Math.min(niceDomainMin, min);
71-
const domainMax = Math.max(niceDomainMax, max);
72+
let domainMax = Math.max(niceDomainMax, max);
7273
const sortedBreaks = breaks.filter(({ end }) => end < domainMax).sort((a, b) => a.start - b.start);
7374
const breaksDomain = d3Ticks(domainMin, domainMax, tickCount, sortedBreaks);
7475
if (last(breaksDomain) < domainMax) {
75-
breaksDomain.push(domainMax);
76+
const nicest = d3LinearNice(0, domainMax - last(breaksDomain), 3);
77+
breaksDomain.push(last(breaksDomain) + last(nicest));
78+
domainMax = last(breaksDomain);
7679
}
7780
const [r0, r1] = [range[0], last(range)] as number[];
7881
const diffDomain = domainMax - domainMin;

0 commit comments

Comments
 (0)