nivo
nivo copied to clipboard
Upgrading Nivo scatterplot from 0.73 to 0.79 broke custom colors
Describe/explain the bug After upgrading Nivo and it's respective scatterplot package from 0.73.0 to 0.79.0/1, all of my scatterplot's custom color function broke.
A snippet of my code is as follows:
export type CustomDatum = {
x: string;
y: number;
trait: string;
total: string;
item: ESOItem;
quant: number;
quality: string | undefined;
};
<ResponsiveScatterPlot
data={[{ id: "Item", data }]}
colors={(d: CustomDatum) => {
switch (colorPreset) {
case ColorPreset.QUALITY: {
return (
((gradient.current as GradientQualityGenerator)?.(
d.quality as keyof typeof QualityColors
) as unknown as string) ?? "#00F"
);
}
case ColorPreset.QUANTITY: {
return (
((gradient.current as GradientQuantityGenerator)?.(
d.quant
) as unknown as string) ?? "#00F"
);
}
case ColorPreset.TRAIT: {
return (
((gradient.current as GradientTraitGenerator)?.(
d.trait as keyof typeof TraitColors
) as unknown as string) ?? "#00F"
);
}
default: {
return "#00F";
}
}
}}
/>
For version 0.73, it looked like the color property had the type OrdinalColorScaleConfig
which in my use case became OrdinalColorScaleConfigCustomFunction<Datum>
.
For version 0.79, it seems like the generic type was pre-set to
OrdinalColorScaleConfig<{
serieId: ScatterPlotRawSerie<RawDatum>['id'];
}>
when I print the value the function received on the new version, the only info I get back is the series ID. I no longer have access to the data of the corresponding point.
On the otherhand, my custom tooltips still work as intended as the generic used is the data model of the chart ScatterPlotTooltip<RawDatum>
.
Is this an intended change? If so, what is the new way of accessing a nodes data from a custom colors function?
Desktop (please complete the following information):
- OS: Ubuntu
- Browser: Firefox
Hi @NicolasNewman, I changed this because it causes issues with legends, the legends are computed automatically for each series, but then if the colors aren't defined per series, we cannot compute them automatically.
I see, that makes more sense. Would it be possible to add a mode that ignores the colors of the legend in favor of allowing the user to specify their own function that relies on the nodes fields to determine the color? That was unfortunately functionality I heavily relied on. If you have a specific way of tackling it in mind, I'd be willing to work on a PR for it.
Or, we could introduce another property to compute the points color while preserving the legends, this could be useful in cases where the point color is a variant of the main series color.
What should the behavior of this property be? From what I understand of the internals, the approach I'm thinking is nodeColor: (datum: RawDatum) => string | null
would either return a string for the node's color computed from RawDatum, overwriting colors
, or null if it should default to using colors
for that node. What are your thoughts on that approach?
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Did something like nodeColor as proposed by @NicolasNewman get implemented? Currently trying to implement custom colours for a set of 250 nodes to no avail.
I have node.color string values, but they break any time I try to access them outside of console.log.
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Thanks to this post I managed to build the feature I needed!
Unfortunately that required me to rollback to version 0.73.0
as described by @NicolasNewman.
Here is an use case of how one can use such feature: 😊
https://user-images.githubusercontent.com/181076/185995149-0ece696f-3e57-4106-8516-767501bbdcb6.mov
This is still an issue for us.
Any updates on this issue?
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!
Downgrading to 0.73.0
worked for me
I'd also love this to be supported easily. I get the initial reason why this was changed initially but I feel there's a set of valid use cases that could benefit from this ask – specially if you don't care about legends/multiple series.
For the time being, for those who don't like the idea of downgrading, another way to achieve this is by creating a custom node.
For example, using typescript, and just caring about the node's x value:
// Get color based on x value
const valueToColor = (value: number) => {
return value > 1 ? "red" : "blue";
}
// Custom node
const Node: ScatterPlotNode<ScatterPlotDatum> = ({
node,
}: ScatterPlotNodeProps<ScatterPlotDatum>) => (
<circle
cx={node.x}
cy={node.y}
r={node.size / 2}
fill={valueToColor(node.data.x as number)}
/>
);
And then make sure your ResponsiveScatterPlot
uses your custom node (i.e. nodeComponent={Node}
)