Skip to content

Commit

Permalink
reuse channels
Browse files Browse the repository at this point in the history
  • Loading branch information
Fil committed Oct 23, 2023
1 parent a93cc56 commit c6c0be5
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 24 deletions.
68 changes: 44 additions & 24 deletions src/marks/difference.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,27 @@ export function differenceY(
ariaLabel = "difference",
positiveAriaLabel = `positive ${ariaLabel}`,
negativeAriaLabel = `negative ${ariaLabel}`,
stroke,
strokeOpacity,
tip,
channels,
...options
} = {}
) {
return marks(
// The positive area goes from the top (0) down to the reference value
// y2, and is clipped by an area going from y1 to the top (0).
area(data, {
// The positive area goes from the top (0) down to the reference value y2, and
// is clipped by an area going from y1 to the top (0). It computes the
// channels which are then reused by the negative area and the line.
const areaPositive = area(
data,
maybeDifferenceChannelsY({
x1,
x2,
y1,
y2,
fill: positiveColor,
fillOpacity: positiveOpacity,
...options,
tip,
// todo render
render: function (index, scales, channels, dimensions, context, next) {
const wrapper = create("svg:g", context);
Expand All @@ -70,22 +75,27 @@ export function differenceY(
wrapper.append(() => g);
return wrapper.node();
}
}),
})
);

return marks(
areaPositive,

// The negative area goes from the bottom (height) up to the reference value
// y2, and is clipped by an area going from y1 to the top (0).
area(data, {
x1,
x2,
y1,
y2,
x1: [],
x2: [],
y1: [],
y2: [],
fill: negativeColor,
fillOpacity: negativeOpacity,
...options,
render: function (index, scales, channels, dimensions, context, next) {
const wrapper = create("svg:g", context);
const clip = getClipId();
const {x1: X1, y1: Y1, x2: X2 = X1} = channels;
const {values} = context.getMarkState(areaPositive);
const {x1: X1, y1: Y1, x2: X2 = X1, y2: Y2} = values;
const {height} = dimensions;
wrapper
.append("clipPath")
Expand All @@ -98,11 +108,7 @@ export function differenceY(
const g = next(
index,
scales,
{
...channels,
x1: X2,
y1: new Float32Array(Y1.length).fill(height)
},
{...channels, x1: X2, y1: new Float32Array(Y1.length).fill(height), x2: X2, y2: Y2},
dimensions,
context
);
Expand All @@ -115,21 +121,35 @@ export function differenceY(
}),

// reference line
lineY(data, maybeDifferenceChannelsY({x: x1, y: y1, y2, tip, ...options}))
lineY(data, {
x: [],
y: [],
render: function (index, scales, channels, dimensions, context, next) {
const {values} = context.getMarkState(areaPositive);
const {x1: X1, y1: Y1} = values;
return next(index, scales, {...channels, x: X1, y: Y1}, dimensions, context);
},
stroke,
strokeOpacity,
...options
})
);
}

// Adds the y2 and difference channels for the default tip mark.
function maybeDifferenceChannelsY(options) {
if (!options.tip) return options;
const [Y1, setY1] = column(options.y);
const [Y2, setY2] = column(options.y2);
// Adds the difference channels for the default tip mark. Materializes
// x1, y1 and y2.
function maybeDifferenceChannelsY({x1, y1, y2, ...options}) {
if (!options.tip) return {x1, y1, y2, ...options};
const [X1, setX] = column(x1);
const [Y1, setY1] = column(y1);
const [Y2, setY2] = column(y2);
const [D, setD] = column();
options = transform(options, function (data, facets) {
const Y1 = setY1(valueof(data, options.y));
const Y2 = setY2(valueof(data, options.y2));
setX(valueof(data, x1));
const Y1 = setY1(valueof(data, y1));
const Y2 = setY2(valueof(data, y2));
setD(Float64Array.from(Y1, (y1, i) => y1 - Y2[i]));
return {data, facets};
});
return {channels: {x: true, y: true, y2: Y2, difference: D}, ...options, y: Y1};
return {x1: X1, y1: Y1, y2: Y2, channels: {x: X1, y1: true, y2: true, difference: D}, ...options};
}
Loading

0 comments on commit c6c0be5

Please sign in to comment.