1
- import { group } from "d3" ;
2
1
import { sqrt3 } from "../symbols.js" ;
3
- import { identity , maybeColumn , maybeColorChannel , valueof } from "../options.js" ;
4
- import { hasOutput , maybeOutputs } from "./group.js" ;
2
+ import { identity , maybeColorChannel , valueof } from "../options.js" ;
3
+ import { hasOutput , maybeGroup , maybeOutputs , maybeSubgroup } from "./group.js" ;
5
4
import { initialize } from "./initialize.js" ;
6
5
7
6
// We don’t want the hexagons to align with the edges of the plot frame, as that
@@ -18,45 +17,45 @@ export function hexbin(outputs = {fill: "count"}, options = {}) {
18
17
19
18
// TODO filter e.g. to show empty hexbins?
20
19
// TODO disallow x, x1, x2, y, y1, y2 reducers?
21
- function hexbinn ( outputs , { binWidth = 20 , fill , stroke , z , ...options } ) {
20
+ function hexbinn ( outputs , { binWidth = 20 , z , fill , stroke , ...options } ) {
22
21
binWidth = + binWidth ;
23
- const [ GZ , setGZ ] = maybeColumn ( z ) ;
24
22
const [ vfill ] = maybeColorChannel ( fill ) ;
25
23
const [ vstroke ] = maybeColorChannel ( stroke ) ;
26
- const [ GF = fill , setGF ] = maybeColumn ( vfill ) ;
27
- const [ GS = stroke , setGS ] = maybeColumn ( vstroke ) ;
28
- outputs = maybeOutputs ( {
29
- ...setGF && { fill : "first" } ,
30
- ...setGS && { stroke : "first" } ,
31
- ...outputs
32
- } , { fill, stroke, ...options } ) ;
24
+ outputs = maybeOutputs ( outputs , { z, fill, stroke, ...options } ) ;
33
25
return {
34
26
symbol : "hexagon" ,
35
27
...! hasOutput ( outputs , "r" ) && { r : binWidth / 2 } ,
36
- ...! setGF && { fill} ,
37
- ...( ( hasOutput ( outputs , "fill" ) || setGF ) && stroke === undefined ) ? { stroke : "none" } : { stroke} ,
28
+ ...! hasOutput ( outputs , "fill" ) && { fill} ,
29
+ ...( ( hasOutput ( outputs , "fill" ) || vstroke != null ) && stroke === undefined ) ? { stroke : "none" } : { stroke} ,
38
30
...initialize ( options , function ( data , facets , { x : X , y : Y } , scales ) {
39
- if ( setGF ) setGF ( valueof ( data , vfill ) ) ;
40
- if ( setGS ) setGS ( valueof ( data , vstroke ) ) ;
41
- if ( setGZ ) setGZ ( valueof ( data , z ) ) ;
42
- for ( const o of outputs ) o . initialize ( data ) ;
43
31
if ( X === undefined ) throw new Error ( "missing channel: x" ) ;
44
32
if ( Y === undefined ) throw new Error ( "missing channel: y" ) ;
45
33
const x = X . scale !== undefined ? scales [ X . scale ] : identity . transform ;
46
34
const y = Y . scale !== undefined ? scales [ Y . scale ] : identity . transform ;
47
35
X = X . value . map ( x ) ;
48
36
Y = Y . value . map ( y ) ;
49
- const F = setGF && GF . transform ( ) ;
50
- const S = setGS && GS . transform ( ) ;
51
- const Z = setGZ ? GZ . transform ( ) : ( F || S ) ;
37
+ const Z = valueof ( data , z ) ;
38
+ const F = valueof ( data , vfill ) ;
39
+ const S = valueof ( data , vstroke ) ;
40
+ const G = maybeSubgroup ( outputs , Z , F , S ) ;
41
+ if ( Z && ! outputs . find ( r => r . name === "z" ) ) {
42
+ outputs . push ( ...maybeOutputs ( { z : "first" } , { z : Z } ) ) ;
43
+ }
44
+ if ( F && ! outputs . find ( r => r . name === "fill" ) ) {
45
+ outputs . push ( ...maybeOutputs ( { fill : "first" } , { fill : F } ) ) ;
46
+ }
47
+ if ( S && ! outputs . find ( r => r . name === "stroke" ) ) {
48
+ outputs . push ( ...maybeOutputs ( { stroke : "first" } , { stroke : S } ) ) ;
49
+ }
52
50
const binFacets = [ ] ;
53
51
const BX = [ ] ;
54
52
const BY = [ ] ;
55
53
let i = - 1 ;
54
+ for ( const o of outputs ) o . initialize ( data ) ;
56
55
for ( const facet of facets ) {
57
56
const binFacet = [ ] ;
58
57
for ( const o of outputs ) o . scope ( "facet" , facet ) ;
59
- for ( const index of Z ? group ( facet , i => Z [ i ] ) . values ( ) : [ facet ] ) {
58
+ for ( const [ , index ] of maybeGroup ( facet , G ) ) {
60
59
for ( const bin of hbin ( index , X , Y , binWidth ) ) {
61
60
binFacet . push ( ++ i ) ;
62
61
BX . push ( bin . x ) ;
@@ -69,6 +68,9 @@ function hexbinn(outputs, {binWidth = 20, fill, stroke, z, ...options}) {
69
68
const channels = {
70
69
x : { value : BX } ,
71
70
y : { value : BY } ,
71
+ ...Z && { z : { value : Z } } ,
72
+ ...F && { fill : { value : F , scale : true } } ,
73
+ ...S && { stroke : { value : S , scale : true } } ,
72
74
...Object . fromEntries ( outputs . map ( ( { name, output} ) => [ name , { scale : true , binWidth : name === "r" ? binWidth : undefined , value : output . transform ( ) } ] ) )
73
75
} ;
74
76
if ( "r" in channels ) {
0 commit comments