@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
67 lines (62 loc) • 2.63 kB
JavaScript
/**
* Scales the values of a column from one range to another.
*
* This node scales the values of a column from one range to another. The input column must contain
* numerical values. The output column will contain the scaled values. The scaling is done using a
* linear scale, which is a common way to scale values. The linear scale is defined by a domain and a
* range. The domain is the input range of values, and the range is the output range of values.
*
* The domain can be set manually or automatically. If set automatically, the extent of the domain
* is based on the minimum and maximum values of the input column.
*
* By default, the input and output columns are named "value", meaning that the values of the input
* column will be overwritten by the scaled values. You can change the names of the input and output
* columns to something else.
* @category Scales
*/
import { scaleLinear } from "https://esm.sh/d3-scale@4.0.2";
import { extent } from "https://esm.sh/d3-array@3.2.4";
export default function (node) {
const tableIn = node.tableIn({ name: "table" });
const inAttributeIn = node.stringIn({ name: "inAttribute", value: "value" });
const outAttributeIn = node.stringIn({ name: "outAttribute", value: "value" });
const domainTypeIn = node.stringIn({
name: "domainType",
value: "auto",
choices: [
["auto", "Automatic"],
["manual", "Manual"],
],
});
const domainMinIn = node.numberIn({ name: "domainMin", value: 0 });
const domainMaxIn = node.numberIn({ name: "domainMax", value: 1 });
const rangeMinIn = node.numberIn({ name: "rangeMin", value: 0 });
const rangeMaxIn = node.numberIn({ name: "rangeMax", value: 100 });
const tableOut = node.tableOut({ name: "out" });
node.onRender = () => {
// Find the table and column
const table = tableIn.value;
if (!table) {
tableOut.set([]);
return;
}
const attr = inAttributeIn.value;
// Check that at least some rows have the given attribute
const hasAttribute = table.some((row) => row[attr] !== undefined);
if (!hasAttribute) {
tableOut.set(table);
return;
}
// Scale the input values
const inValues = table.map((row) => row[attr]);
let min, max;
if (domainTypeIn.value === "auto") {
[min, max] = extent(inValues);
} else {
[min, max] = [domainMinIn.value, domainMaxIn.value];
}
const scale = scaleLinear().domain([min, max]).range([rangeMinIn.value, rangeMaxIn.value]);
const newTable = table.map((row) => ({ ...row, [outAttributeIn.value]: scale(row[attr]) }));
tableOut.set(newTable);
};
}