color quirks
color sometimes works in strange and mysterious ways.
Categorical or linear scales don't work at the series level, except for lineSeries. ie
<XYPlot height={200} width={200} colorType='category' colorDomain={[0, 1, 2]} colorRange={['yellow', 'blue', 'red']}>
<VerticalBarSeries data={data} color={0} />
</XYPlot>
or
<XYPlot height={200} width={200} colorType='category' colorDomain={[0, 1]} colorRange={[ 'blue', 'red']}>
<VerticalBarSeries data={data} color={0.5} />
</XYPlot>
In both cases, the series will appear black. A scale will be created which will return an undefined value and override the defaults.
still happens https://codepen.io/jckr/pen/yKOpma
BarSeries and MarkSeries appear black in documentation.
I think I'm experiencing the same issue here: https://codepen.io/anon/pen/PaxBaP?editors=0010
I'm having the same issue with a VerticalBarSeries
(NB: <FlexibleXYPlot> can be swapped out for XYPlot)
<FlexibleXYPlot height={350} xType="ordinal">
<VerticalBarSeries animation cluster="things" data={data} />
</FlexibleXYPlot>
- I'm setting a
colorproperty on eachdatalist item to"green"(akargb(0, 128, 0)) <VerticalBarSeries>imports<BarSeries>which maps over every item in thedatalist- It applies these properties in a style object:
style: { opacity: opacityFunctor && opacityFunctor(d), stroke: strokeFunctor && strokeFunctor(d), fill: fillFunctor && fillFunctor(d), ...style }, - The
fillandstrokeproperties come from
andthis._getAttributeFunctor('fill') || this._getAttributeFunctor('color');
respectively.this._getAttributeFunctor('stroke') || this._getAttributeFunctor('color'); this._getAttributeFunctoris defined in<AbstractSeries>which<BarSeries>extends.- It returns
getAttributeFunctor(this.props, attr), wheregetAttributeFunctoris defined inutils/scales-utils - The
propsare plentiful, and the important bits look like this:{ ... colorDomain: (2) ["green", "green"], colorRange: (2) ["#EF5D28", "#FF9833"], data: [...], ... } - The
getAttributeFunctorfunction fromutils/scales-utilslooks like this:export function getAttributeFunctor(props, attr) { const scaleObject = getScaleObjectFromProps(props, attr); if (scaleObject) { const scaleFn = getScaleFnFromScaleObject(scaleObject); return d => scaleFn(_getAttrValue(d, scaleObject.accessor)); } return null; } getScaleObjectFromProps(props, attr)calls_collectScaleObjectFromPropswith the same args.- This creates a
scaleObjectfor use with the underlyingd3libs from the props:
In my case the important ones areconst { [attr]: value, [`_${attr}Value`]: fallbackValue, [`${attr}Range`]: range, // !! [`${attr}Distance`]: distance = 0, [`${attr}BaseValue`]: baseValue, [`${attr}Type`]: type = LINEAR_SCALE_TYPE, [`${attr}NoFallBack`]: noFallBack, [`get${toTitleCase(attr)}`]: accessor = d => d[attr], [`get${toTitleCase(attr)}0`]: accessor0 = d => d[`${attr}0`] } = props; let {[`${attr}Domain`]: domain} = props; // !!colorRangeandcolorDomain - I end up with an
scaleObjectthat looks like the following:{ accessor: ƒ (d), accessor0: ƒ (d), attr: "color", baseValue: undefined, distance: 0, domain: (2) ["rgb(0, 128, 0)", "rgb(0, 128, 0)"], isValue: false, range: (2) ["rgb(239, 93, 40)", "rgb(255, 152, 51)"], type: "linear" } - Back in the
getAttributeFunctorfunction, thescaleObjectis returned - Now
getAttributeFunctorcallsgetScaleFnFromScaleObjectin
The returned function is going to be called with theif (scaleObject) { const scaleFn = getScaleFnFromScaleObject(scaleObject); return d => scaleFn(_getAttrValue(d, attr)); }datalist (d) that is passed in as a prop to theVerticalBarSeriesas<VerticalBarSeries ... data={data} />(rememberopacity: opacityFunctor && opacityFunctor(d)from<BarSeries>) - The
_getAttrValue(d, scaleObject.accessor)returns the expected"green"value in RGB form:rgb(0, 128, 0)But when this is passed to thescaleFn(which comes fromd3), it always returnsrgb(0, 0, 0), and it is this value that gets applied to thestrokeandfillproperties in thedata.mapwithinBarSeries(explaining the black bars).{ opacity: 1, stroke: "rgb(0, 0, 0)", fill: "rgb(0, 0, 0)" }
What I can't figure out is why the scaleFn always returns rgb(0, 0, 0) (black).

It might be a problem with this function in utils/scales-utils:
export function getScaleFnFromScaleObject(scaleObject) {
...
const { type, domain, range } = scaleObject;
/*
My data is:
{
attr: "color",
baseValue: undefined,
...
domain: (2) ["rgb(0, 128, 0)", "rgb(0, 128, 0)"],
...
range: (2) ["rgb(239, 93, 40)", "rgb(255, 152, 51)"],
type: "linear"
}
*/
const modDomain =
( domain[0] === domain[1] ) ? (
( domain[0] === 0 ) ? [-1, 0] : [-domain[0], domain[0]]
) : domain;
/*
My modDomain is:
[NaN, "rgb(0, 128, 0)"]
My range (from above) is:
["rgb(239, 93, 40)", "rgb(255, 152, 51)"]
*/
...
const scale = SCALE_FUNCTIONS[type]()
.domain(modDomain)
.range(range);
...
return scale;
}
That NaN in [NaN, "rgb(0, 128, 0)"] looks pretty suspect, caused by trying to get a negative value of a string in [-domain[0], domain[0]] (aka [-"rgb(0, 128, 0)", "rgb(0, 128, 0)"])
Is there any progress on this issue? I'm using a MarkSerie and everytime I try to set a color string (such as rgb or hex) it appears black no matter what.
Same here with LineMarkSeries!
I'm not sure if this helps. but i used exact same code as @jckr except
- moved colorType='category' colorDomain={[0, 1, 2]} colorRange={['yellow', 'blue', 'red']} props from XYPlot to VerticalBarSeries props
- in data, add color:0~2
const data = [
{x: 0, y: 8, color:0},
{x: 1, y: 5, color:0},
{x: 2, y: 4, color:1},
{x: 3, y: 9, color:1},
{x: 4, y: 1, color:2},
{x: 5, y: 7, color:2},
{x: 6, y: 6, color:1},
{x: 7, y: 3, color:1},
{x: 8, y: 2, color:0},
{x: 9, y: 0, color:1}
];
<div>
<XYPlot height={300} width={300}>
<VerticalBarSeries colorType='category' colorDomain={[0, 1, 2]} colorRange={['yellow', 'blue', 'red']} data={data} />
</XYPlot>
</div>
