1
- import { cross , difference , groups , InternMap , select } from "d3" ;
1
+ import { difference , select } from "d3" ;
2
2
import { Axes , autoAxisTicks , autoScaleLabels } from "./axes.js" ;
3
3
import { Channel , Channels , channelDomain , valueObject } from "./channel.js" ;
4
4
import { Context , create } from "./context.js" ;
5
5
import { defined } from "./defined.js" ;
6
6
import { Dimensions } from "./dimensions.js" ;
7
+ import { facetGroups , facetKeys , facetMap , facetTranslate , filterFacets , maybeFacet } from "./facet.js" ;
7
8
import { Legends , exposeLegends } from "./legends.js" ;
8
9
import {
9
10
arrayify ,
10
11
isDomainSort ,
11
12
isScaleOptions ,
12
13
isTypedArray ,
13
- keyword ,
14
14
map ,
15
15
maybeNamed ,
16
16
range ,
@@ -433,7 +433,7 @@ export function plot(options = {}) {
433
433
for ( const mark of marks ) {
434
434
if ( stateByMark . has ( mark ) ) throw new Error ( "duplicate mark; each mark must be unique" ) ;
435
435
const markFacets =
436
- facetsIndex === undefined
436
+ facetsIndex === undefined || mark . facet === null
437
437
? undefined
438
438
: mark . facet === "auto"
439
439
? mark . data === facet . data
@@ -443,7 +443,8 @@ export function plot(options = {}) {
443
443
? facetsIndex
444
444
: mark . facet === "exclude"
445
445
? facetsExclude || ( facetsExclude = facetsIndex . map ( ( f ) => Uint32Array . from ( difference ( facetIndex , f ) ) ) )
446
- : undefined ;
446
+ : filterFacets ( mark . facet , facetChannels ) ;
447
+
447
448
const { data, facets, channels} = mark . initialize ( markFacets , facetChannels ) ;
448
449
applyScaleTransforms ( channels , options ) ;
449
450
stateByMark . set ( mark , { data, facets, channels} ) ;
@@ -668,10 +669,7 @@ export class Mark {
668
669
this . sort = isDomainSort ( sort ) ? sort : null ;
669
670
this . initializer = initializer ( options ) . initializer ;
670
671
this . transform = this . initializer ? options . transform : basic ( options ) . transform ;
671
- this . facet =
672
- facet == null || facet === false
673
- ? null
674
- : keyword ( facet === true ? "include" : facet , "facet" , [ "auto" , "include" , "exclude" ] ) ;
672
+ this . facet = maybeFacet ( facet , data ) ;
675
673
channels = maybeNamed ( channels ) ;
676
674
if ( extraChannels !== undefined ) channels = { ...maybeNamed ( extraChannels ) , ...channels } ;
677
675
if ( defaults !== undefined ) channels = { ...styles ( this , options , defaults ) , ...channels } ;
@@ -693,6 +691,7 @@ export class Mark {
693
691
694
692
if ( this . transform != null ) {
695
693
// If the mark has a transform, reindex facets that overlap
694
+ // TODO optimize
696
695
const overlap = new Set ( ) ;
697
696
const reindex = new Map ( ) ;
698
697
let j = data . length ;
@@ -834,77 +833,6 @@ function nolabel(axis) {
834
833
: Object . assign ( Object . create ( axis ) , { label : undefined } ) ;
835
834
}
836
835
837
- // Unlike facetGroups, which returns groups in order of input data, this returns
838
- // keys in order of the associated scale’s domains.
839
- function facetKeys ( { fx, fy} ) {
840
- return fx && fy ? cross ( fx . domain ( ) , fy . domain ( ) ) : fx ? fx . domain ( ) : fy . domain ( ) ;
841
- }
842
-
843
- // Returns an array of [[key1, index1], [key2, index2], …] representing the data
844
- // indexes associated with each facet. For two-dimensional faceting, each key
845
- // is a two-element array; see also facetMap.
846
- function facetGroups ( index , { fx, fy} ) {
847
- return fx && fy ? facetGroup2 ( index , fx , fy ) : fx ? facetGroup1 ( index , fx ) : facetGroup1 ( index , fy ) ;
848
- }
849
-
850
- function facetGroup1 ( index , { value : F } ) {
851
- return groups ( index , ( i ) => F [ i ] ) ;
852
- }
853
-
854
- function facetGroup2 ( index , { value : FX } , { value : FY } ) {
855
- return groups (
856
- index ,
857
- ( i ) => FX [ i ] ,
858
- ( i ) => FY [ i ]
859
- ) . flatMap ( ( [ x , xgroup ] ) => xgroup . map ( ( [ y , ygroup ] ) => [ [ x , y ] , ygroup ] ) ) ;
860
- }
861
-
862
- // This must match the key structure returned by facetGroups.
863
- function facetTranslate ( fx , fy ) {
864
- return fx && fy
865
- ? ( [ kx , ky ] ) => `translate(${ fx ( kx ) } ,${ fy ( ky ) } )`
866
- : fx
867
- ? ( kx ) => `translate(${ fx ( kx ) } ,0)`
868
- : ( ky ) => `translate(0,${ fy ( ky ) } )` ;
869
- }
870
-
871
- function facetMap ( { fx, fy} ) {
872
- return new ( fx && fy ? FacetMap2 : FacetMap ) ( ) ;
873
- }
874
-
875
- class FacetMap {
876
- constructor ( ) {
877
- this . _ = new InternMap ( ) ;
878
- }
879
- has ( key ) {
880
- return this . _ . has ( key ) ;
881
- }
882
- get ( key ) {
883
- return this . _ . get ( key ) ;
884
- }
885
- set ( key , value ) {
886
- return this . _ . set ( key , value ) , this ;
887
- }
888
- }
889
-
890
- // A Map-like interface that supports paired keys.
891
- class FacetMap2 extends FacetMap {
892
- has ( [ key1 , key2 ] ) {
893
- const map = super . get ( key1 ) ;
894
- return map ? map . has ( key2 ) : false ;
895
- }
896
- get ( [ key1 , key2 ] ) {
897
- const map = super . get ( key1 ) ;
898
- return map && map . get ( key2 ) ;
899
- }
900
- set ( [ key1 , key2 ] , value ) {
901
- const map = super . get ( key1 ) ;
902
- if ( map ) map . set ( key2 , value ) ;
903
- else super . set ( key1 , new InternMap ( [ [ key2 , value ] ] ) ) ;
904
- return this ;
905
- }
906
- }
907
-
908
836
// expands an array or typed array to make room for n values
909
837
function expandArray ( values , n ) {
910
838
if ( isTypedArray ( values ) ) {
0 commit comments