1- import { extent , namespaces } from "d3" ;
1+ import { extent , namespaces , polygonCentroid } from "d3" ;
22import { create } from "../context.js" ;
33import { composeRender } from "../mark.js" ;
44import { hasXY , identity , indexOf } from "../options.js" ;
@@ -8,14 +8,36 @@ import {maybeIdentityX, maybeIdentityY} from "../transforms/identity.js";
88import { maybeIntervalX , maybeIntervalY } from "../transforms/interval.js" ;
99import { maybeStackX , maybeStackY } from "../transforms/stack.js" ;
1010import { BarX , BarY } from "./bar.js" ;
11+ import { initializer } from "../transforms/basic.js" ;
1112
1213const waffleDefaults = {
1314 ariaLabel : "waffle"
1415} ;
1516
1617export class WaffleX extends BarX {
1718 constructor ( data , { unit = 1 , gap = 1 , round, render, multiple, ...options } = { } ) {
18- super ( data , { ...options , render : composeRender ( render , waffleRender ( "x" ) ) } , waffleDefaults ) ;
19+ super (
20+ data ,
21+ initializer ( { ...options , render : composeRender ( render , waffleRender ( "x" ) ) } , function ( data , facets , channels ) {
22+ const n = channels . x1 . value . length ;
23+ const X = new Float64Array ( n ) ;
24+ const Y = new Float64Array ( n ) ;
25+ return {
26+ data,
27+ facets,
28+ channels : {
29+ ...channels ,
30+ x1 : { value : X , scale : null , source : null } ,
31+ x2 : { value : X , scale : null , source : null } ,
32+ y1 : { value : Y , scale : null , source : null } ,
33+ y2 : { value : Y , scale : null , source : null } ,
34+ s1 : { ...channels . x1 , source : null } ,
35+ s2 : { ...channels . x2 , source : null }
36+ }
37+ } ;
38+ } ) ,
39+ waffleDefaults
40+ ) ;
1941 this . unit = Math . max ( 0 , unit ) ;
2042 this . gap = + gap ;
2143 this . round = maybeRound ( round ) ;
@@ -25,7 +47,28 @@ export class WaffleX extends BarX {
2547
2648export class WaffleY extends BarY {
2749 constructor ( data , { unit = 1 , gap = 1 , round, render, multiple, ...options } = { } ) {
28- super ( data , { ...options , render : composeRender ( render , waffleRender ( "y" ) ) } , waffleDefaults ) ;
50+ super (
51+ data ,
52+ initializer ( { ...options , render : composeRender ( render , waffleRender ( "y" ) ) } , function ( data , facets , channels ) {
53+ const n = channels . y1 . value . length ;
54+ const X = new Float64Array ( n ) ;
55+ const Y = new Float64Array ( n ) ;
56+ return {
57+ data,
58+ facets,
59+ channels : {
60+ ...channels ,
61+ x1 : { value : X , scale : null , source : null } ,
62+ x2 : { value : X , scale : null , source : null } ,
63+ y1 : { value : Y , scale : null , source : null } ,
64+ y2 : { value : Y , scale : null , source : null } ,
65+ s1 : { ...channels . y1 , source : null } ,
66+ s2 : { ...channels . y2 , source : null }
67+ }
68+ } ;
69+ } ) ,
70+ waffleDefaults
71+ ) ;
2972 this . unit = Math . max ( 0 , unit ) ;
3073 this . gap = + gap ;
3174 this . round = maybeRound ( round ) ;
@@ -37,8 +80,8 @@ function waffleRender(y) {
3780 return function ( index , scales , values , dimensions , context ) {
3881 const { unit, gap, rx, ry, round} = this ;
3982 const { document} = context ;
40- const Y1 = values . channels [ ` ${ y } 1` ] . value ;
41- const Y2 = values . channels [ ` ${ y } 2` ] . value ;
83+ const Y1 = values . channels [ "s1" ] . value ;
84+ const Y2 = values . channels [ "s2" ] . value ;
4285
4386 // We might not use all the available bandwidth if the cells don’t fit evenly.
4487 const barwidth = this [ y === "y" ? "_width" : "_height" ] ( scales , values , dimensions ) ;
@@ -74,6 +117,9 @@ function waffleRender(y) {
74117 if ( rx != null ) basePatternRect . setAttribute ( "rx" , rx ) ;
75118 if ( ry != null ) basePatternRect . setAttribute ( "ry" , ry ) ;
76119
120+ const X = values . channels . x1 . value ;
121+ const Y = values . channels . y1 . value ;
122+
77123 return create ( "svg:g" , context )
78124 . call ( applyIndirectStyles , this , dimensions , context )
79125 . call ( this . _transform , this , scales )
@@ -95,13 +141,13 @@ function waffleRender(y) {
95141 . enter ( )
96142 . append ( "path" )
97143 . attr ( "transform" , y === "y" ? template `translate(${ x0 } ,${ y0 } )` : template `translate(${ y0 } ,${ x0 } )` )
98- . attr (
99- "d" ,
100- ( i ) =>
101- `M ${ wafflePoints ( round ( Y1 [ i ] / unit ) , round ( Y2 [ i ] / unit ) , multiple )
102- . map ( transform )
103- . join ( "L" ) } Z`
104- )
144+ . attr ( "d" , ( i ) => {
145+ const pts = wafflePoints ( round ( Y1 [ i ] / unit ) , round ( Y2 [ i ] / unit ) , multiple ) . map ( transform ) ;
146+ const [ xa , ya ] = polygonCentroid ( pts ) ;
147+ X [ i ] = xa + ( typeof x0 === "function" ? x0 ( i ) - barwidth / 2 : x0 ) ;
148+ Y [ i ] = ya + ( typeof y0 === "function" ? y0 ( i ) : y0 ) ;
149+ return `M ${ pts . join ( "L" ) } Z`;
150+ } )
105151 . attr ( "fill" , ( i ) => `url(#${ patternId } -${ i } )` )
106152 . attr ( "stroke" , this . stroke == null ? null : ( i ) => `url(#${ patternId } -${ i } )` )
107153 )
@@ -198,12 +244,14 @@ function spread(domain) {
198244 return max - min ;
199245}
200246
201- export function waffleX ( data , options = { } ) {
247+ export function waffleX ( data , { tip, ...options } = { } ) {
248+ if ( tip === true ) tip = "xy" ;
202249 if ( ! hasXY ( options ) ) options = { ...options , y : indexOf , x2 : identity } ;
203- return new WaffleX ( data , maybeStackX ( maybeIntervalX ( maybeIdentityX ( options ) ) ) ) ;
250+ return new WaffleX ( data , maybeStackX ( maybeIntervalX ( maybeIdentityX ( { ... options , tip } ) ) ) ) ;
204251}
205252
206- export function waffleY ( data , options = { } ) {
253+ export function waffleY ( data , { tip, ...options } = { } ) {
254+ if ( tip === true ) tip = "xy" ;
207255 if ( ! hasXY ( options ) ) options = { ...options , x : indexOf , y2 : identity } ;
208- return new WaffleY ( data , maybeStackY ( maybeIntervalY ( maybeIdentityY ( options ) ) ) ) ;
256+ return new WaffleY ( data , maybeStackY ( maybeIntervalY ( maybeIdentityY ( { ... options , tip } ) ) ) ) ;
209257}
0 commit comments