@@ -2,7 +2,7 @@ import {extent, namespaces} from "d3";
22import { valueObject } from "../channel.js" ;
33import { create } from "../context.js" ;
44import { composeRender } from "../mark.js" ;
5- import { hasXY , identity , indexOf , isObject } from "../options.js" ;
5+ import { hasXY , identity , indexOf , isObject , keyword } from "../options.js" ;
66import { applyChannelStyles , applyDirectStyles , applyIndirectStyles , getPatternId } from "../style.js" ;
77import { template } from "../template.js" ;
88import { initializer } from "../transforms/basic.js" ;
@@ -16,19 +16,19 @@ const waffleDefaults = {
1616} ;
1717
1818export class WaffleX extends BarX {
19- constructor ( data , { unit = 1 , gap = 1 , round, multiple, ...options } = { } ) {
19+ constructor ( data , { unit, gap = 1 , round, multiple, ...options } = { } ) {
2020 super ( data , wafflePolygon ( "x" , options ) , waffleDefaults ) ;
21- this . unit = Math . max ( 0 , unit ) ;
21+ this . unit = maybeUnit ( unit ) ;
2222 this . gap = + gap ;
2323 this . round = maybeRound ( round ) ;
2424 this . multiple = maybeMultiple ( multiple ) ;
2525 }
2626}
2727
2828export class WaffleY extends BarY {
29- constructor ( data , { unit = 1 , gap = 1 , round, multiple, ...options } = { } ) {
29+ constructor ( data , { unit, gap = 1 , round, multiple, ...options } = { } ) {
3030 super ( data , wafflePolygon ( "y" , options ) , waffleDefaults ) ;
31- this . unit = Math . max ( 0 , unit ) ;
31+ this . unit = maybeUnit ( unit ) ;
3232 this . gap = + gap ;
3333 this . round = maybeRound ( round ) ;
3434 this . multiple = maybeMultiple ( multiple ) ;
@@ -40,7 +40,7 @@ function wafflePolygon(y, options) {
4040 const y1 = `${ y } 1` ;
4141 const y2 = `${ y } 2` ;
4242 return initializer ( waffleRender ( options ) , function ( data , facets , channels , scales , dimensions ) {
43- const { round, unit } = this ;
43+ const { round} = this ;
4444 const Y1 = channels [ y1 ] . value ;
4545 const Y2 = channels [ y2 ] . value ;
4646
@@ -49,8 +49,18 @@ function wafflePolygon(y, options) {
4949 const barwidth = this [ y === "y" ? "_width" : "_height" ] ( scales , xy , dimensions ) ;
5050 const barx = this [ y === "y" ? "_x" : "_y" ] ( scales , xy , dimensions ) ;
5151
52+ // Auto unit: if the scale of a unit makes it so small that it is invisible,
53+ // or conversely insanely large, adopt a different power of 10^3.
54+ const p = scaleof ( scales . scales [ y ] ) ; // pixel length per unit of 1
55+ let { unit} = this ;
56+ if ( unit === "auto" ) {
57+ const area = barwidth * p ; // pixel area per unit of 1
58+ if ( area < 5 || area > 5e4 ) unit = 1000 ** Math . ceil ( ( 1 - Math . log10 ( area ) ) / 3 ) ;
59+ else unit = 1 ;
60+ }
61+
5262 // The length of a unit along y in pixels.
53- const scale = unit * scaleof ( scales . scales [ y ] ) ;
63+ const scale = unit * p ;
5464
5565 // The number of cells on each row (or column) of the waffle.
5666 const { multiple = Math . max ( 1 , Math . floor ( Math . sqrt ( barwidth / scale ) ) ) } = this ;
@@ -301,3 +311,11 @@ function waffleTip(tip) {
301311 ? { ...tip , maxRadius : Infinity }
302312 : undefined ;
303313}
314+
315+ function maybeUnit ( unit = "auto" ) {
316+ if ( typeof unit === "number" ) {
317+ if ( unit <= 0 || ! isFinite ( unit ) ) throw new Error ( `invalid unit: ${ unit } ` ) ;
318+ return unit ;
319+ }
320+ return keyword ( unit , "unit" , [ "auto" ] ) ;
321+ }
0 commit comments