@@ -8,7 +8,7 @@ import {Mark} from "./mark.js";
88import { axisFx , axisFy , axisX , axisY , gridFx , gridFy , gridX , gridY } from "./marks/axis.js" ;
99import { frame } from "./marks/frame.js" ;
1010import { arrayify , isColor , isIterable , isNone , isScaleOptions , map , yes , maybeIntervalTransform } from "./options.js" ;
11- import { createProjection } from "./projection.js" ;
11+ import { createProjection , getGeometryChannels } from "./projection.js" ;
1212import { createScales , createScaleFunctions , autoScaleRange , exposeScales } from "./scales.js" ;
1313import { innerDimensions , outerDimensions } from "./scales.js" ;
1414import { position , registry as scaleRegistry } from "./scales/index.js" ;
@@ -404,15 +404,26 @@ function addScaleChannels(channelsByScale, stateByMark, filter = yes) {
404404 const channel = channels [ name ] ;
405405 const { scale} = channel ;
406406 if ( scale != null && filter ( scale ) ) {
407- const scaleChannels = channelsByScale . get ( scale ) ;
408- if ( scaleChannels !== undefined ) scaleChannels . push ( channel ) ;
409- else channelsByScale . set ( scale , [ channel ] ) ;
407+ if ( scale === "projection" ) {
408+ // TODO only do this if there’s no projection
409+ const [ x , y ] = getGeometryChannels ( channel ) ;
410+ addScaleChannel ( channelsByScale , "x" , x ) ;
411+ addScaleChannel ( channelsByScale , "y" , y ) ;
412+ } else {
413+ addScaleChannel ( channelsByScale , scale , channel ) ;
414+ }
410415 }
411416 }
412417 }
413418 return channelsByScale ;
414419}
415420
421+ function addScaleChannel ( channelsByScale , scale , channel ) {
422+ const scaleChannels = channelsByScale . get ( scale ) ;
423+ if ( scaleChannels !== undefined ) scaleChannels . push ( channel ) ;
424+ else channelsByScale . set ( scale , [ channel ] ) ;
425+ }
426+
416427// Returns the facet groups, and possibly fx and fy channels, associated with
417428// the top-level facet option {data, x, y}.
418429function maybeTopFacet ( facet , options ) {
@@ -486,8 +497,8 @@ function inferAxes(marks, channelsByScale, options) {
486497 } = options ;
487498
488499 // Disable axes if the corresponding scale is not present.
489- if ( projection || ( ! isScaleOptions ( x ) && ! hasScaleChannel ( "x" , marks ) ) ) xAxis = xGrid = null ;
490- if ( projection || ( ! isScaleOptions ( y ) && ! hasScaleChannel ( "y" , marks ) ) ) yAxis = yGrid = null ;
500+ if ( projection || ( ! isScaleOptions ( x ) && ! hasPositionChannel ( "x" , marks ) ) ) xAxis = xGrid = null ;
501+ if ( projection || ( ! isScaleOptions ( y ) && ! hasPositionChannel ( "y" , marks ) ) ) yAxis = yGrid = null ;
491502 if ( ! channelsByScale . has ( "fx" ) ) fxAxis = fxGrid = null ;
492503 if ( ! channelsByScale . has ( "fy" ) ) fyAxis = fyGrid = null ;
493504
@@ -613,10 +624,11 @@ function hasAxis(marks, k) {
613624 return marks . some ( ( m ) => m . ariaLabel ?. startsWith ( prefix ) ) ;
614625}
615626
616- function hasScaleChannel ( k , marks ) {
627+ function hasPositionChannel ( k , marks ) {
617628 for ( const mark of marks ) {
618629 for ( const key in mark . channels ) {
619- if ( mark . channels [ key ] . scale === k ) {
630+ const { scale} = mark . channels [ key ] ;
631+ if ( scale === k || scale === "projection" ) {
620632 return true ;
621633 }
622634 }
0 commit comments