@@ -10,7 +10,7 @@ import {axisFx, axisFy, axisX, axisY, gridFx, gridFy, gridX, gridY} from "./mark
1010import { frame } from "./marks/frame.js" ;
1111import { tip } from "./marks/tip.js" ;
1212import { arrayify , isColor , isIterable , isNone , isScaleOptions , map , yes , maybeIntervalTransform } from "./options.js" ;
13- import { createProjection } from "./projection.js" ;
13+ import { createProjection , getGeometryChannels } from "./projection.js" ;
1414import { createScales , createScaleFunctions , autoScaleRange , exposeScales } from "./scales.js" ;
1515import { innerDimensions , outerDimensions } from "./scales.js" ;
1616import { position , registry as scaleRegistry } from "./scales/index.js" ;
@@ -416,15 +416,26 @@ function addScaleChannels(channelsByScale, stateByMark, filter = yes) {
416416 const channel = channels [ name ] ;
417417 const { scale} = channel ;
418418 if ( scale != null && filter ( scale ) ) {
419- const scaleChannels = channelsByScale . get ( scale ) ;
420- if ( scaleChannels !== undefined ) scaleChannels . push ( channel ) ;
421- else channelsByScale . set ( scale , [ channel ] ) ;
419+ if ( scale === "projection" ) {
420+ // TODO only do this if there’s no projection
421+ const [ x , y ] = getGeometryChannels ( channel ) ;
422+ addScaleChannel ( channelsByScale , "x" , x ) ;
423+ addScaleChannel ( channelsByScale , "y" , y ) ;
424+ } else {
425+ addScaleChannel ( channelsByScale , scale , channel ) ;
426+ }
422427 }
423428 }
424429 }
425430 return channelsByScale ;
426431}
427432
433+ function addScaleChannel ( channelsByScale , scale , channel ) {
434+ const scaleChannels = channelsByScale . get ( scale ) ;
435+ if ( scaleChannels !== undefined ) scaleChannels . push ( channel ) ;
436+ else channelsByScale . set ( scale , [ channel ] ) ;
437+ }
438+
428439// Returns the facet groups, and possibly fx and fy channels, associated with
429440// the top-level facet option {data, x, y}.
430441function maybeTopFacet ( facet , options ) {
@@ -518,8 +529,8 @@ function inferAxes(marks, channelsByScale, options) {
518529 } = options ;
519530
520531 // Disable axes if the corresponding scale is not present.
521- if ( projection || ( ! isScaleOptions ( x ) && ! hasScaleChannel ( "x" , marks ) ) ) xAxis = xGrid = null ;
522- if ( projection || ( ! isScaleOptions ( y ) && ! hasScaleChannel ( "y" , marks ) ) ) yAxis = yGrid = null ;
532+ if ( projection || ( ! isScaleOptions ( x ) && ! hasPositionChannel ( "x" , marks ) ) ) xAxis = xGrid = null ;
533+ if ( projection || ( ! isScaleOptions ( y ) && ! hasPositionChannel ( "y" , marks ) ) ) yAxis = yGrid = null ;
523534 if ( ! channelsByScale . has ( "fx" ) ) fxAxis = fxGrid = null ;
524535 if ( ! channelsByScale . has ( "fy" ) ) fyAxis = fyGrid = null ;
525536
@@ -647,10 +658,11 @@ function hasAxis(marks, k) {
647658 return marks . some ( ( m ) => m . ariaLabel ?. startsWith ( prefix ) ) ;
648659}
649660
650- function hasScaleChannel ( k , marks ) {
661+ function hasPositionChannel ( k , marks ) {
651662 for ( const mark of marks ) {
652663 for ( const key in mark . channels ) {
653- if ( mark . channels [ key ] . scale === k ) {
664+ const { scale} = mark . channels [ key ] ;
665+ if ( scale === k || scale === "projection" ) {
654666 return true ;
655667 }
656668 }
0 commit comments