plouc / nivo

nivo provides a rich set of dataviz components, built on top of the awesome d3 and React libraries
https://nivo.rocks
MIT License
13.19k stars 1.03k forks source link

How to fill colour for specific region in responsive line charts #2075

Closed ramanujamgond closed 1 year ago

ramanujamgond commented 2 years ago

Hello,

I am struggling to highlight the area that has higher values in the responsive line charts. I want to color the area or region which has higher values or the values are higher for a particular date. I am enclosing a screenshot of the desired results.

Screenshot 2022-07-13 134443

I am trying to show month-wise dates on the x-axis and on the y-axis, I am showing the rates. Rates may vary based on the dates, sometimes it goes up, and sometimes it goes down. I want to highlight the area which has a higher rate value on different dates along with different colors to highlight the area.

So far I am able to render the line charts. Along with the data for rates and dates. I am having a hard time achieving the above-mentioned chart.

I am enclosing the component code. Kindly go through the code.

const lineData = [
        {
            "id": "Rates",
            "data": [
                {
                    "x": "13 Jul",
                    "y": 212
                },
                {
                    "x": "14 Jul",
                    "y": 8
                },
                {
                    "x": "15 Jul",
                    "y": 134
                },
                {
                    "x": "16 Jul",
                    "y": 74
                },
                {
                    "x": "17 Jul",
                    "y": 113
                },
                {
                    "x": "18 Jul",
                    "y": 66
                },
                {
                    "x": "19 Jul",
                    "y": 11
                },
                {
                    "x": "20 Jul",
                    "y": 178
                },
                {
                    "x": "21 Jul",
                    "y": 268
                },
                {
                    "x": "22 Jul",
                    "y": 210
                },
                {
                    "x": "23 Jul",
                    "y": 215
                },
                {
                    "x": "24 Jul",
                    "y": 17
                }
            ]
        }
    ]

<div style={{ height: 600 }}>
    <ResponsiveLine
        data={lineData}
        margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
        xScale={{ type: 'point' }}
        enableGridX={false}
        colors={["rgb(200, 67, 182)"]}
        enableArea={true}
        // areaOpacity={1}
        enableSlices={false}
        crosshairType="cross"
        yScale={{
            type: 'linear',
            min: 'auto',
            max: 'auto',
            stacked: true,
            reverse: false
        }}
        yFormat=" >-.2f"
        axisTop={null}
        axisRight={null}
        axisBottom={{
            // orient: 'bottom',
            tickSize: 5,
            tickPadding: 5,
            tickRotation: 0,
            legend: 'Dates',
            legendOffset: 36,
            legendPosition: 'middle'
        }}
        axisLeft={{
            // orient: 'left',
            tickSize: 5,
            tickPadding: 5,
            tickRotation: 0,
            legend: 'Rates',
            legendOffset: -40,
            legendPosition: 'middle'
        }}
        pointSize={10}
        pointColor={{ theme: 'background' }}
        pointBorderWidth={2}
        pointBorderColor={{ from: 'serieColor' }}
        pointLabelYOffset={-12}
        useMesh={true}
        legends={[
            {
                anchor: 'bottom-right',
                direction: 'column',
                justify: false,
                translateX: 100,
                translateY: 0,
                itemsSpacing: 0,
                itemDirection: 'left-to-right',
                itemWidth: 80,
                itemHeight: 20,
                itemOpacity: 0.75,
                symbolSize: 12,
                symbolShape: 'circle',
                symbolBorderColor: 'rgba(0, 0, 0, .5)',
                effects: [
                    {
                        on: 'hover',
                        style: {
                            itemBackground: 'rgba(0, 0, 0, .03)',
                            itemOpacity: 1
                        }
                    }
                ]
            }
        ]}
    />
</div>
itschrislow commented 2 years ago

The answer lies in layers and some d3.

// imports
import { area } from "d3-shape";
import { Defs } from "@nivo/core";
import { ResponsiveLine } from "@nivo/line";
// layers prop to add in ResponsiveLine component
layers={[
  "grid",
  "markers",
  "areas",
  // component added below
  AreaLayer,
  "lines",
  "slices",
  "axes",
  "points",
  "legends",
]}
// AreaLayer component included in layers prop array
const AreaLayer = ({ series, xScale, yScale, innerHeight }: any) => {
  const areaGenerator = area()
    .x((d: any) => xScale(d.data.x))
    .y0((d: any) => innerHeight)
    .y1((d: any) => yScale(d.data.y));

  return (
    <>
      <Defs
        defs={[
          {
            id: "pattern",
            type: "patternLines",
            background: "transparent",
            color: "#3daff7",
            lineWidth: 1,
            spacing: 6,
            rotation: -45,
          },
        ]}
      />
      <path
        // idk how you want to compute the area with higher values or the values are higher for a particular date 
        // so this is just an example for the blue area
        d={areaGenerator(series[0].data.slice(3, 6))}
        fill="url(#pattern)"
        fillOpacity={0.6}
        stroke="#3daff7"
        strokeWidth={2}
      />
    </>
  );
};

Refer to the storybook for line charts with custom layers here as reference.

stale[bot] commented 2 years ago

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!

stale[bot] commented 1 year ago

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!