1
- import { extent , namespaces } from "d3" ;
1
+ import { extent , namespaces , polygonCentroid } from "d3" ;
2
2
import { create } from "../context.js" ;
3
3
import { composeRender } from "../mark.js" ;
4
4
import { hasXY , identity , indexOf } from "../options.js" ;
@@ -8,14 +8,36 @@ import {maybeIdentityX, maybeIdentityY} from "../transforms/identity.js";
8
8
import { maybeIntervalX , maybeIntervalY } from "../transforms/interval.js" ;
9
9
import { maybeStackX , maybeStackY } from "../transforms/stack.js" ;
10
10
import { BarX , BarY } from "./bar.js" ;
11
+ import { initializer } from "../transforms/basic.js" ;
11
12
12
13
const waffleDefaults = {
13
14
ariaLabel : "waffle"
14
15
} ;
15
16
16
17
export class WaffleX extends BarX {
17
18
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
+ ) ;
19
41
this . unit = Math . max ( 0 , unit ) ;
20
42
this . gap = + gap ;
21
43
this . round = maybeRound ( round ) ;
@@ -25,7 +47,28 @@ export class WaffleX extends BarX {
25
47
26
48
export class WaffleY extends BarY {
27
49
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
+ ) ;
29
72
this . unit = Math . max ( 0 , unit ) ;
30
73
this . gap = + gap ;
31
74
this . round = maybeRound ( round ) ;
@@ -37,8 +80,8 @@ function waffleRender(y) {
37
80
return function ( index , scales , values , dimensions , context ) {
38
81
const { unit, gap, rx, ry, round} = this ;
39
82
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 ;
42
85
43
86
// We might not use all the available bandwidth if the cells don’t fit evenly.
44
87
const barwidth = this [ y === "y" ? "_width" : "_height" ] ( scales , values , dimensions ) ;
@@ -74,6 +117,9 @@ function waffleRender(y) {
74
117
if ( rx != null ) basePatternRect . setAttribute ( "rx" , rx ) ;
75
118
if ( ry != null ) basePatternRect . setAttribute ( "ry" , ry ) ;
76
119
120
+ const X = values . channels . x1 . value ;
121
+ const Y = values . channels . y1 . value ;
122
+
77
123
return create ( "svg:g" , context )
78
124
. call ( applyIndirectStyles , this , dimensions , context )
79
125
. call ( this . _transform , this , scales )
@@ -95,13 +141,13 @@ function waffleRender(y) {
95
141
. enter ( )
96
142
. append ( "path" )
97
143
. 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
+ } )
105
151
. attr ( "fill" , ( i ) => `url(#${ patternId } -${ i } )` )
106
152
. attr ( "stroke" , this . stroke == null ? null : ( i ) => `url(#${ patternId } -${ i } )` )
107
153
)
@@ -198,12 +244,14 @@ function spread(domain) {
198
244
return max - min ;
199
245
}
200
246
201
- export function waffleX ( data , options = { } ) {
247
+ export function waffleX ( data , { tip, ...options } = { } ) {
248
+ if ( tip === true ) tip = "xy" ;
202
249
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 } ) ) ) ) ;
204
251
}
205
252
206
- export function waffleY ( data , options = { } ) {
253
+ export function waffleY ( data , { tip, ...options } = { } ) {
254
+ if ( tip === true ) tip = "xy" ;
207
255
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 } ) ) ) ) ;
209
257
}
0 commit comments