diff --git a/src/channel.d.ts b/src/channel.d.ts index 2637240f33..4e0a8026e0 100644 --- a/src/channel.d.ts +++ b/src/channel.d.ts @@ -82,3 +82,9 @@ export type ChannelDomainSort = { } & ChannelDomainOptions; export type ChannelReducers = {[key in ChannelName]?: ChannelReducerSpec | null}; + +/** The abstract (unscaled) values, and associated scale, per channel. */ +export type ChannelStates = {[key in ChannelName]?: {value: any[]; scale: ScaleName | null}}; + +/** The possibly-scaled values for each channel. */ +export type ChannelValues = {[key in ChannelName]?: any[]} & {channels: ChannelStates}; diff --git a/src/channel.js b/src/channel.js index b56e826e62..7848741854 100644 --- a/src/channel.js +++ b/src/channel.js @@ -24,12 +24,14 @@ export function createChannels(channels, data) { // TODO Use Float64Array for scales with numeric ranges, e.g. position? export function valueObject(channels, scales) { - return Object.fromEntries( + const values = Object.fromEntries( Object.entries(channels).map(([name, {scale: scaleName, value}]) => { const scale = scaleName == null ? null : scales[scaleName]; return [name, scale == null ? value : map(value, scale)]; }) ); + values.channels = channels; // expose channel state for advanced usage + return values; } // If the channel uses the "auto" scale (or equivalently true), infer the scale diff --git a/src/mark.d.ts b/src/mark.d.ts index 103fc94f41..8913fd95e5 100644 --- a/src/mark.d.ts +++ b/src/mark.d.ts @@ -1,10 +1,10 @@ -import type {Channels, ChannelDomainSort, ChannelName, ChannelValue, ChannelValueSpec} from "./channel.js"; +import type {ChannelDomainSort, Channels, ChannelValue, ChannelValues, ChannelValueSpec} from "./channel.js"; import type {Context} from "./context.js"; import type {Dimensions} from "./dimensions.js"; import type {Facet, FacetAnchor} from "./facet.js"; import type {plot} from "./plot.js"; import type {ScaleFunctions} from "./scales.js"; -import type {InitializerFunction, TransformFunction, SortOrder} from "./transforms/basic.js"; +import type {InitializerFunction, SortOrder, TransformFunction} from "./transforms/basic.js"; export type FrameAnchor = | "middle" @@ -22,7 +22,7 @@ export type Data = Iterable | ArrayLike; export type RenderFunction = ( index: number[], scales: ScaleFunctions, - values: {[key in ChannelName]?: any[]}, + values: ChannelValues, dimensions: Dimensions, context: Context ) => SVGElement | null; diff --git a/src/marks/raster.js b/src/marks/raster.js index a2989d16f4..fd601e3ced 100644 --- a/src/marks/raster.js +++ b/src/marks/raster.js @@ -97,11 +97,11 @@ export class Raster extends AbstractRaster { scale(channels, {color, ...scales}, context) { return super.scale(channels, scales, context); } - render(index, scales, channels, dimensions, context) { - const color = scales.color ?? ((x) => x); - const {x: X, y: Y} = channels; + render(index, scales, values, dimensions, context) { + const color = scales[values.channels.fill?.scale] ?? ((x) => x); + const {x: X, y: Y} = values; const {document} = context; - const [x1, y1, x2, y2] = renderBounds(channels, dimensions, context); + const [x1, y1, x2, y2] = renderBounds(values, dimensions, context); const dx = x2 - x1; const dy = y2 - y1; const {pixelSize: k, width: w = Math.round(Math.abs(dx) / k), height: h = Math.round(Math.abs(dy) / k)} = this; @@ -110,7 +110,7 @@ export class Raster extends AbstractRaster { // Interpolate the samples to fill the raster grid. If interpolate is null, // then a continuous function is being sampled, and the raster grid is // already aligned with the canvas. - let {fill: F, fillOpacity: FO} = channels; + let {fill: F, fillOpacity: FO} = values; let offset = 0; if (this.interpolate) { const kx = w / dx; diff --git a/test/output/rasterVapor2.html b/test/output/rasterVapor2.html new file mode 100644 index 0000000000..8856b7bc8d --- /dev/null +++ b/test/output/rasterVapor2.html @@ -0,0 +1,96 @@ +
+ + + + + + 0 + + + + 2 + + + + 4 + + + + 6 + + + + + + + + + + + + + + + + + −80 + −60 + −40 + −20 + 0 + 20 + 40 + 60 + 80 + + + + + + + + + + + + −150 + −100 + −50 + 0 + 50 + 100 + 150 + + + + + + + +
\ No newline at end of file diff --git a/test/plots/raster-vapor.ts b/test/plots/raster-vapor.ts index 95e5097ccb..abfe1d7674 100644 --- a/test/plots/raster-vapor.ts +++ b/test/plots/raster-vapor.ts @@ -17,6 +17,25 @@ export async function rasterVapor() { }); } +export async function rasterVapor2() { + return Plot.plot({ + color: {scheme: "blues", legend: true}, + x: {transform: (x) => x - 180}, + y: {transform: (y) => 90 - y}, + marks: [ + Plot.raster(await vapor(), { + width: 360, + height: 180 + }), + Plot.raster(await vapor(), { + width: 360, + height: 180, + fill: {value: (d) => (d > 4 ? "red" : null), scale: null} + }) + ] + }); +} + export async function contourVapor() { return Plot.plot({ width: 960,