Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8386138

Browse files
authored
fix: improve automatic compact notation detection (#278)
This pull request refactors how compact notation is determined for axistick labels in both the `AxisX.svelte` and `AxisY.svelte` components.The logic for deciding when to use compact notation (e.g., "1K" for1,000) is now extracted into a derived store for clarity andconsistency, and the code for formatting tick labels is updated to usethis new logic.**Axis tick label formatting improvements:*** Extracted the logic for determining whether to use compact notationinto a new `$derived` store called `useCompactNotation` in both`AxisX.svelte` and `AxisY.svelte`, improving code readability andmaintainability.[[1]](diffhunk://#diff-63aa453fb923bd6f90586018b1310d90e17b66f9cb818352d8235c23482573f2R117-R127)[[2]](diffhunk://#diff-409da8ecf2c0213a5e18a5a3d62148f893868b6dcbc6433fc4cd2aff1d0e1e0fR115-R122)* Updated the tick label formatting function to use the new`useCompactNotation` store instead of recalculating the logic inline,ensuring consistent behavior and reducing code duplication.[[1]](diffhunk://#diff-63aa453fb923bd6f90586018b1310d90e17b66f9cb818352d8235c23482573f2L135-R147)[[2]](diffhunk://#diff-409da8ecf2c0213a5e18a5a3d62148f893868b6dcbc6433fc4cd2aff1d0e1e0fL133-R142)
1 parentc8a5bf3 commit8386138

File tree

4 files changed

+126
-8
lines changed

4 files changed

+126
-8
lines changed

‎src/lib/marks/AxisX.svelte‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import {autoTicks }from'$lib/helpers/autoTicks.js';
1919
import {resolveScaledStyles }from'$lib/helpers/resolve.js';
2020
import {getPlotDefaults }from'$lib/hooks/plotDefaults.js';
21+
import {extent }from'd3-array';
2122
2223
interfaceAxisXMarkPropsextendsOmit<
2324
BaseMarkProps<Datum>,
@@ -114,6 +115,21 @@
114115
)
115116
);
116117
118+
const useCompactNotation=$derived.by(()=> {
119+
const range=
120+
extent(plot.scales.x.domain).filter(
121+
(d):disnumber=>typeofd==='number'&&Number.isFinite(d)
122+
)?? [];
123+
124+
if (range[0]===undefined||range[1]===undefined)returnfalse;
125+
const crossesZero=range[0]<=0&&range[1]>=0;
126+
if (crossesZero)returntrue;
127+
const magnitudes=range.map((d)=>
128+
d===0?-Infinity:Math.floor(Math.log10(Math.abs(d)))
129+
);
130+
returnmagnitudes[0]!==magnitudes[1];
131+
});
132+
117133
const tickFmt=$derived(tickFormat||plot.options.x.tickFormat);
118134
119135
const useTickFormat=$derived(
@@ -132,10 +148,8 @@
132148
:// auto
133149
(d:RawValue)=>
134150
Intl.NumberFormat(plot.options.locale, {
135-
// use compact notation if range covers multipe magnitudes
136-
...(newSet(ticks.map(Math.log10).map(Math.round)).size>1
137-
? { notation:'compact' }
138-
: {}),
151+
// use compact notation if range covers multiple magnitudes
152+
...(useCompactNotation? { notation:'compact' }: {}),
139153
...DEFAULTS.numberFormat,
140154
style:plot.options.x.percent?'percent':'decimal'
141155
}).format(d)

‎src/lib/marks/AxisY.svelte‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import {autoTicks }from'$lib/helpers/autoTicks.js';
1818
import {resolveScaledStyles }from'$lib/helpers/resolve.js';
1919
import {getPlotDefaults }from'$lib/hooks/plotDefaults.js';
20+
import {extent }from'd3-array';
2021
2122
interfaceAxisYMarkPropsextendsOmit<
2223
BaseMarkProps<Datum>,
@@ -112,6 +113,21 @@
112113
)
113114
);
114115
116+
const useCompactNotation=$derived.by(()=> {
117+
const range=
118+
extent(plot.scales.y.domain).filter(
119+
(d):disnumber=>typeofd==='number'&&Number.isFinite(d)
120+
)?? [];
121+
122+
if (range[0]===undefined||range[1]===undefined)returnfalse;
123+
const crossesZero=range[0]<=0&&range[1]>=0;
124+
if (crossesZero)returntrue;
125+
const magnitudes=range.map((d)=>
126+
d===0?-Infinity:Math.floor(Math.log10(Math.abs(d)))
127+
);
128+
returnmagnitudes[0]!==magnitudes[1];
129+
});
130+
115131
const tickFmt=$derived(tickFormat||plot.options.y.tickFormat);
116132
117133
const useTickFormat=$derived(
@@ -130,10 +146,8 @@
130146
:// auto
131147
(d:RawValue)=>
132148
Intl.NumberFormat(plot.options.locale, {
133-
// use compact notation if range covers multipe magnitudes
134-
...(newSet(ticks.map(Math.log10).map(Math.round)).size>1
135-
? { notation:'compact' }
136-
: {}),
149+
// use compact notation if range covers multiple magnitudes
150+
...(useCompactNotation? { notation:'compact' }: {}),
137151
...DEFAULTS.numberFormat,
138152
style:plot.options.y.percent?'percent':'decimal'
139153
}).format(d)

‎src/tests/axisX.test.ts‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,51 @@ describe('AxisX mark', () => {
274274
expect(checkTicks.mock.calls[1]).toStrictEqual([20,1,[0,20,40,60,80,100]]);
275275
});
276276

277+
it('keeps plain notation within a single magnitude domain',()=>{
278+
const{ container}=render(AxisXTest,{
279+
props:{
280+
plotArgs:{width:400,x:{domain:[100,900]}},
281+
axisArgs:{data:[100,500,900]}
282+
}
283+
});
284+
285+
constticks=Array.from(
286+
container.querySelectorAll('g.axis-x > g.tick')asNodeListOf<SVGGElement>
287+
);
288+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
289+
expect(tickValues).toStrictEqual(['100','500','900']);
290+
});
291+
292+
it('switches to compact notation when domain spans magnitudes',()=>{
293+
const{ container}=render(AxisXTest,{
294+
props:{
295+
plotArgs:{width:400,x:{type:'log',domain:[0.001,1000]}},
296+
axisArgs:{data:[0.001,1,1000]}
297+
}
298+
});
299+
300+
constticks=Array.from(
301+
container.querySelectorAll('g.axis-x > g.tick')asNodeListOf<SVGGElement>
302+
);
303+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
304+
expect(tickValues).toStrictEqual(['0.001','1','1K']);
305+
});
306+
307+
it('switches to compact notation when domain crosses zero across magnitudes',()=>{
308+
const{ container}=render(AxisXTest,{
309+
props:{
310+
plotArgs:{width:400,x:{domain:[-10000,10000]}},
311+
axisArgs:{data:[-10000,0,10000]}
312+
}
313+
});
314+
315+
constticks=Array.from(
316+
container.querySelectorAll('g.axis-x > g.tick')asNodeListOf<SVGGElement>
317+
);
318+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
319+
expect(tickValues).toStrictEqual(['-10K','0','10K']);
320+
});
321+
277322
it('removes duplicate ticks',()=>{
278323
const{ container}=render(AxisXTest,{
279324
props:{

‎src/tests/axisY.test.ts‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,49 @@ describe('AxisY mark', () => {
195195
expect(checkTicks.mock.calls[0]).toStrictEqual([0,0,[0,20,40,60,80,100]]);
196196
expect(checkTicks.mock.calls[1]).toStrictEqual([20,1,[0,20,40,60,80,100]]);
197197
});
198+
199+
it('keeps plain notation within a single magnitude domain',()=>{
200+
const{ container}=render(AxisYTest,{
201+
props:{
202+
plotArgs:{height:300,y:{domain:[100,900]}},
203+
axisArgs:{data:[100,500,900]}
204+
}
205+
});
206+
207+
constticks=Array.from(
208+
container.querySelectorAll('g.axis-y > g.tick')asNodeListOf<SVGGElement>
209+
);
210+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
211+
expect(tickValues).toStrictEqual(['100','500','900']);
212+
});
213+
214+
it('switches to compact notation when domain spans magnitudes',()=>{
215+
const{ container}=render(AxisYTest,{
216+
props:{
217+
plotArgs:{height:300,y:{type:'log',domain:[0.001,1000]}},
218+
axisArgs:{data:[0.001,1,1000]}
219+
}
220+
});
221+
222+
constticks=Array.from(
223+
container.querySelectorAll('g.axis-y > g.tick')asNodeListOf<SVGGElement>
224+
);
225+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
226+
expect(tickValues).toStrictEqual(['0.001','1','1K']);
227+
});
228+
229+
it('switches to compact notation when domain crosses zero across magnitudes',()=>{
230+
const{ container}=render(AxisYTest,{
231+
props:{
232+
plotArgs:{height:300,y:{domain:[-10000,10000]}},
233+
axisArgs:{data:[-10000,0,10000]}
234+
}
235+
});
236+
237+
constticks=Array.from(
238+
container.querySelectorAll('g.axis-y > g.tick')asNodeListOf<SVGGElement>
239+
);
240+
consttickValues=ticks.map((t)=>t.querySelector('text')?.textContent);
241+
expect(tickValues).toStrictEqual(['-10K','0','10K']);
242+
});
198243
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp