@@ -2,7 +2,7 @@ import {extent, namespaces} from "d3";
2
2
import { valueObject } from "../channel.js" ;
3
3
import { create } from "../context.js" ;
4
4
import { composeRender } from "../mark.js" ;
5
- import { hasXY , identity , indexOf } from "../options.js" ;
5
+ import { hasXY , identity , indexOf , keyword } from "../options.js" ;
6
6
import { applyChannelStyles , applyDirectStyles , applyIndirectStyles , getPatternId } from "../style.js" ;
7
7
import { template } from "../template.js" ;
8
8
import { initializer } from "../transforms/basic.js" ;
@@ -16,21 +16,21 @@ const waffleDefaults = {
16
16
} ;
17
17
18
18
export class WaffleX extends BarX {
19
- constructor ( data , { unit = 1 , gap = 1 , round, render, multiple, ...options } = { } ) {
19
+ constructor ( data , { unit, gap = 1 , round, render, multiple, ...options } = { } ) {
20
20
options = initializer ( { ...options , render : composeRender ( render , waffleRender ( "x" ) ) } , waffleInitializer ( "x" ) ) ;
21
21
super ( data , options , waffleDefaults ) ;
22
- this . unit = Math . max ( 0 , unit ) ;
22
+ this . unit = maybeUnit ( unit ) ;
23
23
this . gap = + gap ;
24
24
this . round = maybeRound ( round ) ;
25
25
this . multiple = maybeMultiple ( multiple ) ;
26
26
}
27
27
}
28
28
29
29
export class WaffleY extends BarY {
30
- constructor ( data , { unit = 1 , gap = 1 , round, render, multiple, ...options } = { } ) {
30
+ constructor ( data , { unit, gap = 1 , round, render, multiple, ...options } = { } ) {
31
31
options = initializer ( { ...options , render : composeRender ( render , waffleRender ( "y" ) ) } , waffleInitializer ( "y" ) ) ;
32
32
super ( data , options , waffleDefaults ) ;
33
- this . unit = Math . max ( 0 , unit ) ;
33
+ this . unit = maybeUnit ( unit ) ;
34
34
this . gap = + gap ;
35
35
this . round = maybeRound ( round ) ;
36
36
this . multiple = maybeMultiple ( multiple ) ;
@@ -39,8 +39,7 @@ export class WaffleY extends BarY {
39
39
40
40
function waffleInitializer ( y ) {
41
41
return function ( data , facets , channels , scales , dimensions ) {
42
- const { round, unit} = this ;
43
-
42
+ const { round} = this ;
44
43
const values = valueObject ( channels , scales ) ;
45
44
const Y1 = values . channels [ `${ y } 1` ] . value ;
46
45
const Y2 = values . channels [ `${ y } 2` ] . value ;
@@ -49,8 +48,18 @@ function waffleInitializer(y) {
49
48
const barwidth = this [ y === "y" ? "_width" : "_height" ] ( scales , values , dimensions ) ;
50
49
const barx = this [ y === "y" ? "_x" : "_y" ] ( scales , values , dimensions ) ;
51
50
51
+ // Auto unit: if the scale of a unit makes it so small that it is invisible,
52
+ // or conversely insanely large, adopt a different power of 10**3.
53
+ const p = scaleof ( scales . scales [ y ] ) ; // pixel length per unit of 1
54
+ let { unit} = this ;
55
+ if ( unit === "auto" ) {
56
+ const area = barwidth * p ; // pixel area per unit of 1
57
+ if ( area < 5 || area > 5e4 ) unit = 1000 ** Math . ceil ( ( 1 - Math . log10 ( area ) ) / 3 ) ;
58
+ else unit = 1 ;
59
+ }
60
+
52
61
// The length of a unit along y in pixels.
53
- const scale = unit * scaleof ( scales . scales [ y ] ) ;
62
+ const scale = unit * p ;
54
63
55
64
// The number of cells on each row (or column) of the waffle.
56
65
const { multiple = Math . max ( 1 , Math . floor ( Math . sqrt ( barwidth / scale ) ) ) } = this ;
@@ -281,3 +290,7 @@ export function waffleY(data, {tip, ...options} = {}) {
281
290
if ( ! hasXY ( options ) ) options = { ...options , x : indexOf , y2 : identity } ;
282
291
return new WaffleY ( data , { tip, ...maybeStackY ( maybeIntervalY ( maybeIdentityY ( options ) ) ) } ) ;
283
292
}
293
+
294
+ function maybeUnit ( unit = "auto" ) {
295
+ return typeof unit === "number" ? Math . max ( 0 , unit ) : keyword ( unit , "unit" , [ "auto" ] ) ;
296
+ }
0 commit comments