Closed Kibo007 closed 6 years ago
Yes in general that's possible. While the cleaner approach is still in a branch.. you could copy paste and rename the current chart and add a new axis component inside. Then fix both axes settings. One to be on the left and one on the right side.
if is not problem for you can you illustrate this in jsfiddle?
Would be from big help :)
This is only a temporary way to do this but:
const MyCustomAreaChart = React.createClass({
mixins: [
DefaultPropsMixin,
HeightWidthMixin,
ArrayifyMixin,
StackAccessorMixin,
StackDataMixin,
DefaultScalesMixin,
TooltipMixin
],
propTypes: {
interpolate: string,
stroke: func
},
getDefaultProps() {
return {
interpolate: 'linear',
stroke: d3.scale.category20()
};
},
_tooltipHtml(d, position) {
const {x, y0, y, values} = this.props;
const xScale = this._xScale;
const yScale = this._yScale;
const xValueCursor = xScale.invert(position[0]);
const xBisector = d3.bisector(e => x(e)).right;
let xIndex = xBisector(values(d[0]), xScale.invert(position[0]));
xIndex = xIndex == values(d[0]).length ? xIndex - 1 : xIndex;
const xIndexRight = xIndex == values(d[0]).length ? xIndex - 1 : xIndex;
const xValueRight = x(values(d[0])[xIndexRight]);
const xIndexLeft = xIndex == 0 ? xIndex : xIndex - 1;
const xValueLeft = x(values(d[0])[xIndexLeft]);
if (Math.abs(xValueCursor - xValueRight) < Math.abs(xValueCursor - xValueLeft)) {
xIndex = xIndexRight;
} else {
xIndex = xIndexLeft;
}
const yValueCursor = yScale.invert(position[1]);
const yBisector = d3.bisector(e => y0(values(e)[xIndex]) + y(values(e)[xIndex])).left;
let yIndex = yBisector(d, yValueCursor);
yIndex = yIndex == d.length ? yIndex - 1 : yIndex;
const yValue = y(values(d[yIndex])[xIndex]);
const yValueCumulative = y0(values(d[d.length - 1])[xIndex]) + y(values(d[d.length - 1])[xIndex]);
const xValue = x(values(d[yIndex])[xIndex]);
const xPos = xScale(xValue);
const yPos = yScale(y0(values(d[yIndex])[xIndex]) + yValue);
return [this.props.tooltipHtml(yValue, yValueCumulative, xValue), xPos, yPos];
},
render() {
const {
height,
width,
margin,
colorScale,
interpolate,
stroke,
values,
label,
x,
y,
y0,
xAxis,
yAxis
} = this.props;
const data = this._data;
const innerWidth = this._innerWidth;
const innerHeight = this._innerHeight;
const xScale = this._xScale;
const yScale = this._yScale;
let line = d3.svg.line()
.x(e => xScale(x(e)))
.y(e => yScale(y0(e) + y(e)))
.interpolate(interpolate);
let area = d3.svg.area()
.x(e => xScale(x(e)))
.y0(e => yScale(yScale.domain()[0] + y0(e)))
.y1(e => yScale(y0(e) + y(e)))
.interpolate(interpolate);
return (
<div>
<Chart height={height} width={width} margin={margin}>
<DataSet
data={data}
line={line}
area={area}
colorScale={colorScale}
stroke={stroke}
label={label}
values={values}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
/>
<Axis
className="x axis"
orientation="bottom"
scale={xScale}
height={innerHeight}
width={innerWidth}
{...xAxis}
/>
<Axis
className="y axis"
orientation="left"
scale={yScale}
height={innerHeight}
width={innerWidth}
{...yAxis}
/>
<Axis
className="y axis"
orientation="right"
scale={yScale}
height={innerHeight}
width={innerWidth}
{...yAxis}
/>
{this.props.children}
</Chart>
<Tooltip {...this.state.tooltip}/>
</div>
);
}
});
Notice there are 3 axes. You probably want to pass different scales to the "left" and "right" axes. That depends on your data.
Thank you, I just add orientation param trough props and adjust your component to accept it
React.createElement(Axis, _extends({
className: "y axis",
orientation: yOrientation,
scale: yScale,
height: innerHeight,
width: innerWidth
}, yAxis)),
so than I rendered 2 times graph one with yAxis orientation left and once with different data set orientation right
<ResponsiveAreaChart
data={data}
height={400}
yOrientation="left"
yAxis={{zero: 0, outerTickSize: 0, tickPadding: 15, innerTickSize: 0, className: "yAxis"}}
xAxis={{outerTickSize: 0, tickPadding: 25, innerTickSize: 0, className: "xAxis", tickFormat: timeFormatMH}}
margin={{top: 10, bottom: 50, left: 50, right: 50}}/>
</div>
<div className={styles.y2Area}>
<ResponsiveAreaChart
data={data2}
height={400}
yOrientation="right"
xAxis={{outerTickSize: 0, tickPadding: 0, innerTickSize: 0, className: "xAxis", tickValues: null}}
yAxis={{outerTickSize: 0, tickPadding: 15, innerTickSize: 0, className: "yAxis", tickFormat: x => `${x}%`}}
margin={{top: 10, bottom: 50, left: 50, right: 50}}/>
</div>
and than made them one above other so they look like
That's another way to do it! Great you figured something out :)
Would you like to accept this changes and merge them to master? I would just add possibility that people can change orientation instead that is hardcoded? Can make it to be default left but if you pass orientation than that one is used.
Sure! Maybe it would be good to integrate it with the current axis property.
Ok let me than prepare it and will make PR today.
Thank you :)
So to use it from npm we need to wait your release? How often you are making releases?
I just pushed the new 0.6.5 release to npm. Normally I try to release after each pullrequest. Btw it would be very nice if the change you made could be added to all other charts too. Maybe if you find the time.
I will have to work soon on analytic section of our app so will need to use lot of others graphs so probably will need to do more changes on some components. I will do this changes you mention soon as I find time.
thnx
Looking forward to your improvements!
Is it possible to make with react-d3-components multiple y axis?