1

What we want to solve

I want to separate the colors of the graph from 0 to plus or minus, but I have tried several galleries and looked at Issues, but I can't get the graph to render properly. I am very sorry, but I would appreciate your answer.

I tried using and also < Threshold > but could not complete it.

Assumed chart

enter image description here

Code

First, AreaClose was used. Never mind about color transparency and gradients.

import { LoginContentsWithSideBar } from "src/components/projects/LoginContentsWithSideBar"
import { mediaQueryTabletMaxWidth } from "src/constants/deviceDimensions"
import { COLORS } from "src/constants/colors"
import styled from "styled-components"
import { Card } from "src/components/projects/Manage/Assets/Card"
import { LinePath, AreaClosed } from "@visx/shape"
import { scaleTime, scaleLinear } from "@visx/scale"
import { AxisLeft, AxisBottom} from "@visx/axis"
import { Group } from "@visx/group"
import { GridRows, GridColumns } from "@visx/grid"
import dayjs from "dayjs"
import { curveBasis, curveMonotoneX } from '@visx/curve';
import { Threshold } from '@visx/threshold';
import { extent } from 'd3-array';
import { LinearGradient } from '@visx/gradient';

type Props = {
  date: Date
  value: number
}

type DatePoint = Props[]

const data: DatePoint = [
  { date: new Date("2023-01"), value: -10 },
  { date: new Date("2023-02"), value: -100 },
  { date: new Date("2023-03"), value: 105 },
  { date: new Date("2023-04"), value: 100 },
  { date: new Date("2023-05"), value: 100 },
  { date: new Date("2023-06"), value: 105 },
  { date: new Date("2023-07"), value: 100 },
  { date: new Date("2023-08"), value: 105 },
  { date: new Date("2023-09"), value: 100 },
  { date: new Date("2023-10"), value: 100 },
  { date: new Date("2023-11"), value: -105 },
  { date: new Date("2023-12"), value: -100 },
  { date: new Date("2024-01"), value: 105 },
  { date: new Date("2024-02"), value: -100 },
  { date: new Date("2024-03"), value: 105 },
  { date: new Date("2024-04"), value: 100 },
  { date: new Date("2024-05"), value: 100 },
  { date: new Date("2024-06"), value: 105 },
]

const formatDate = (date: unknown) => {
  if (!(date instanceof Date)) {
    return ""
  }
  return dayjs(date).format("YYYY/MM")
}

export const TestChart = () => {
  const width = 1100
  const height = 600
  const margin = { top: 20, right: 20, bottom: 30, left: 50 }

  const getDate = d => d.date;
const getValue = d => d.value;

  const negativeData = data.filter( d => d.value <= 0)
  const positiveData = data.filter( d => d.value >= 0)
  


  const xMax = width - margin.left - margin.right
  const yMax = height - margin.top - margin.bottom
  // scales
  const xScale = scaleTime({
    domain: domain,
    range: [margin.left, width - margin.right],
  });
  
  const yScale = scaleLinear({
    domain: [Math.min(0, ...data.map(d => d.value)), Math.max(...data.map(d => d.value))],
    range: [height - margin.bottom, margin.top],
  });

  return (
        <svg width={width} height={height}>
            <GridRows scale={profitScale} width={xMax} height={yMax} left={50} stroke="#4D4D4D" numTicks={10} />
            <GridColumns scale={timeScale} width={1200} height={550} top={20} stroke="#4D4D4D" numTicks={15} />


            <AreaClosed
              data={positiveData}
              yScale={yScale}
              x={d => xScale(getDate(d))}
              y={d => yScale(getValue(d))}
              stroke="red"
              fill="red"
            />

            <AreaClosed
              data={negativeData}
              yScale={yScale}
              x={d => xScale(getDate(d))}
              y={d => yScale(getValue(d))}
              stroke="blue"
              fill="blue"
            />
            <AxisLeft
              scale={profitScale}
              left={margin.left}
              stroke="#4D4D4D"
              hideTicks
              tickLabelProps={() => ({
                fill: COLORS.NEUTRAL100,
                fontSize: 14,
                textAnchor: "end",
                dy: "0.2em",
                dx: "-0.5em",
              })}
            />
            <AxisBottom
              scale={timeScale}
              top={height - margin.bottom}
              tickFormat={formatDate}
              stroke="#4D4D4D"
              hideTicks
              tickLabelProps={() => ({
                fill: COLORS.NEUTRAL100,
                textAnchor: "middle",
                fontSize: 11,
                dy: "0.2em",
              })}
              tickValues={data.map(d => d.date)}
            />
        </svg>

  )
}


enter image description here

Next we used Threshold I will only include the code for the changes.

  const timeScale = scaleTime({
    domain: [
      new Date(Math.min(...data.map((d) => d.date.getTime()))),
      new Date(Math.max(...data.map((d) => d.date.getTime()))),
    ],
    range: [margin.left, width - margin.right],
  })

  const valueScale = scaleLinear({
    domain: [Math.min(...data.map((d) => d.value)), Math.max(...data.map((d) => d.value))],
    range: [height - margin.bottom, margin.top],
  })
return(
・・・
          <Threshold
            id={"1"}
            data={data}
            x={d => timeScale(d.date)}
            y0={d => valueScale(Math.min(0, d.value))}
            y1={d => valueScale(Math.max(0, d.value))}
            clipAboveTo={0}
            clipBelowTo={yMax}
            curve={curveBasis}
            belowAreaProps={{
              fill: 'blue',
              fillOpacity: 0.4,
            }}
            aboveAreaProps={{
              fill: 'red',
              fillOpacity: 0.4,
            }}
          />

)

enter image description here

What I tried

0 Answers0