@ndbx/runtime
Version:
The `@ndbx/runtime` package provides a runtime environment to embed NodeBox visualizations directly into React applications. NodeBox is a powerful tool for creating interactive and generative visualizations, and this runtime allows you to integrate those
98 lines (88 loc) • 3.33 kB
JavaScript
/**
* Define a scale to map a data attribute to a visual property of the plot.
*
* Predefined scales are automaticaly applied to the corresponding visual property unless
* attribute and property parameter given.
*
* To define a scale, use Set Plot Scale.
*
* - Band position: Relative position on a band of a stacked, binned, time unit, or band scale.
* For example, the marks will be positioned at the beginning of the band if set to 0, and at
* the middle of the band if set to 0.5.
*
* @category Plot
*/
import { emptyPlot, validateVegaSpec, applyScale } from "project:Utilities";
export default function (node) {
const plotSpecIn = node.specIn({ name: "plotSpecIn", label: "Plot spec" });
node.pushSection("General");
const nameIn = node.stringIn({
name: "scaleName",
label: "Scale name",
value: "xScale",
choices: [
"xScale",
"yScale",
"fillColorScale",
"strokeColorScale",
"sizeScale",
"strokeWidthScale",
"shapeScale",
"opacityScale",
"fillOpacityScale",
"strokeOpacityScale",
"strokeDashScale",
"gridUnitScale",
"<custom>",
],
});
const customNameIn = node.stringIn({ name: "customName", label: "Custom scale name" });
const attrNameIn = node.stringIn({ name: "attrName", label: "Attribute name" });
const propNameIn = node.stringIn({ name: "propName", label: "Property name" });
const bandIn = node.numberIn({ name: "band", label: "Band position" });
node.popSection();
const plotSpecOut = node.specOut({ name: "plotSpecOut", label: "Plot spec out" });
// Function to apply scale in marks
function applyScale_old({ spec, scaleName, plotType, attr, prop, markName, band }) {
const property = prop || scaleDefaults.find((d) => d.scaleName === scaleName).property;
const scaleAttr = attr || scaleDefaults.find((d) => d.scaleName === scaleName).scaleAttr;
let newUpdate = {
scale: scaleName,
field: scaleAttr,
};
const scaleIdx = spec.scales.findIndex((d) => d.name === scaleName);
if (scaleIdx >= 0) {
if (spec.scales[scaleIdx].type === "band") {
newUpdate.band = band;
}
}
if (markName) {
spec.marks.find((d) => d.name === markName).encode.update[property] = newUpdate;
} else if (plotType) {
spec.marks.find((d) => d.name === plotType).encode.update[property] = newUpdate;
} else {
spec.marks.forEach((mark) => {
if (mark.type === "group") {
mark.marks.forEach((submark) => {
submark.encode.update[property] = newUpdate;
});
} else {
mark.encode.update[property] = newUpdate;
}
});
}
}
node.onRender = () => {
let specOut = structuredClone(plotSpecIn.value ? plotSpecIn.value : emptyPlot);
validateVegaSpec(specOut);
// APPLY SCALES
const scaleName = nameIn.value === "<custom>" ? customNameIn.value : nameIn.value;
const scaleAttr = attrNameIn.value
? attrNameIn.value
: nameIn.value === "<custom>"
? "__" + customNameIn.value + "_attr"
: scaleDefaults.find((d) => d.scaleName === scaleName).scaleAttr;
applyScale({ spec: specOut, scaleName: scaleName, prop: propNameIn.value, attr: scaleAttr, band: bandIn.value });
plotSpecOut.set(specOut);
};
}