the x-axis line disappears after drawing a linear plot

By using svg.select("path"), you were re-purposing your axis domain path as a line for the chart. Adding a separate path node, and giving it a class name, fixed it:

Now there is also no more need to subtract yWidth from the y value, which you did because of the transform on the bottom axis.

const useState = React.useState;
const useRef = React.useRef;
const useEffect = React.useEffect;
const select = d3.select;
const scaleLinear = d3.scaleLinear;
const axisBottom = d3.axisBottom;
const axisLeft = d3.axisLeft;
const line = d3.line;
const curveCardinal = d3.curveCardinal;

const DummyPlot = () => {

  const [xAxisData] = useState({
    min: 0,
    max: 16
  });

  const [yAxisData] = useState({
    min: 1000,
    max: 1500
  });

  const [colorPalette] = useState({
    dots: "#1E90FF",
    line: "#8A2BE2"
  });

  const [meta] = useState({
    xWidth: 600,
    yWidth: 300,
    lineStroke: "3px",
    pointRadius: "4px"
  });

  const [points] = useState([{
      y: 1425,
      x: 1
    },
    {
      y: 1435,
      x: 2
    },
    {
      y: 1445,
      x: 3
    },
    {
      y: 1455,
      x: 4
    },
    {
      y: 1455,
      x: 5
    },
    {
      y: 1455,
      x: 6
    },
    {
      y: 1425,
      x: 7
    },
    {
      y: 1125,
      x: 8
    },
    {
      y: 1090,
      x: 9
    },
    {
      y: 1090,
      x: 10
    },
    {
      y: 1250,
      x: 11
    },
    {
      y: 1350,
      x: 12
    },
    {
      y: 1035,
      x: 13
    },
    {
      y: 1150,
      x: 14
    },
    {
      y: 1100,
      x: 15
    }
  ]);

  const svgRef = useRef();

  useEffect(() => {

    if (svgRef.current) {

      const svg = select(svgRef.current);

      // X-AXIS
      const xScale = scaleLinear()
        .domain([xAxisData.min, xAxisData.max])
        .range([0, meta.xWidth]);

      const xAxis = axisBottom(xScale);

      svg
        .select(".x-axis")
        .style("transform", `translateY(${meta.yWidth}px)`)
        .call(xAxis);

      // Y-AXIS
      const yScale = scaleLinear()
        .domain([yAxisData.min, yAxisData.max])
        .range([meta.yWidth, 0]);

      const yAxis = axisLeft(yScale);

      svg
        .select(".y-axis")
        .call(yAxis);

      // LINE PLOT
      const myLine = line()
        .x(value => xScale(value.x))
        .y(value => yScale(value.y))
        .curve(curveCardinal);

      svg
        .selectAll(".line")
        .data([points])
        .join(".line")
        .attr("d", value => myLine(value))
        .attr("fill", "none")
        .attr("stroke", colorPalette.line)
        .attr("stroke-width", meta.lineStroke);

      // DOT PLOT
      svg
        .selectAll("circle")
        .data(points)
        .join("circle")
        .attr("cx", value => xScale(value.x))
        .attr("cy", value => yScale(value.y))
        .attr("r", () => meta.pointRadius)
        .attr("fill", () => colorPalette.dots)
        .attr("stroke", () => colorPalette.dots);
    }

  }, [xAxisData, yAxisData, meta, points, colorPalette]);

  return ( <
    svg viewBox={`0 0 ${meta.xWidth} ${meta.yWidth}`}
        ref = {svgRef} >
      <g className = "x-axis" / >
      <g className = "y-axis" / >
      <path className = "line" / >
    </svg>
  );
}

ReactDOM.render(< DummyPlot />, document.querySelector("body"));
svg {
  width: 80%;
  height: auto;
  background: #eee;
  overflow: visible;
  margin: 5%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top