Maison  >  Article  >  interface Web  >  Créer votre propre graphique linéaire interactif dans ReactJS

Créer votre propre graphique linéaire interactif dans ReactJS

Patricia Arquette
Patricia Arquetteoriginal
2024-10-31 18:14:30537parcourir

Building your own Interactive Line Graph in ReactJS

Composant SVG de base

Tout d'abord, créons un composant SVG simple qui accepte la largeur et la hauteur comme accessoires. Ce sera le point de départ de notre graphique.

import React from "react";

const LineGraph = ({ height, width }) => {
  return <svg height={height} width={width}></svg>;
};

export default LineGraph;

Ajout de l'axe X

Maintenant, ajoutons l'axe X, qui s'étend horizontalement sur le graphique. Nous utiliserons la ligne élément pour cela.

const drawXAxis = () => {
  const middleY = height / 2;

  return (
    <line x1={0} y1={middleY} x2={width} y2={middleY} stroke={lineColor} />
  );
};

Ajout de l'axe Y

Nous utiliserons une autre élément pour dessiner l'axe Y, qui passera verticalement par le centre du graphique.

const drawYAxis = () => {
  const middleX = width / 2;

  return (
    <line x1={middleX} y1={0} x2={middleX} y2={height} stroke={lineColor} />
  );
};

Tracer des coordonnées sous forme de chemin de ligne

L'élément clé d'un graphique linéaire est la ligne reliant différents points. Traçons quelques exemples de coordonnées et connectons-les à l'aide d'un SVG.

const drawPath = () => {
    const pathData = coordinates
      .map((coordinate, index) =>
        index === 0
          ? `M ${coordinate.x} ${coordinate.y}`
          : `L ${coordinate.x} ${coordinate.y}`
      )
      .join(" ");

    return <path d={pathData} stroke={pathColor} fill="none" />;
  };

Option pour remplir la zone sous la ligne

Nous pouvons remplir la zone sous la ligne avec une couleur pour améliorer le graphique. Cela peut être fait en utilisant un élément supplémentaire. Considérez prop isFillArea pour afficher/masquer cette zone.

const drawPath = () => {
  const pathData = coordinates
    .map((coordinate, index) =>
      index === 0
        ? `M ${coordinate.x} ${coordinate.y}`
        : `L ${coordinate.x} ${coordinate.y}`
    )
    .join(" ");

  const middleY = height / 2;
  const svgPath = showFillArea
    ? `${pathData} L ${width} ${middleY} L 0 ${middleY} Z`
    : pathData;
  const fillColor = showFillArea ? areaColor : "none";
  return (
    <path d={svgPath} fill={fillColor} stroke={pathColor} opacity="0.5" />
  );
};

Suivi du curseur

Ajoutons un cercle qui suit le mouvement du curseur sur le chemin du graphique.

Nous aurons besoin d'une référence de notre composant SVG pour accéder à la boîte englobante de l'élément SVG. Également une référence pour notre cercle de suivi qui sera utilisé pour suivre le curseur sur le graphique.

const svgRef = useRef();
const circleRef = useRef();
// ...
const drawTrackingCircle = () => {
  return (
    <circle
      ref={circleRef}
      r={6}
      fill="red"
      style={{ display: "none" }} // Initially hidden
    />
  );
};
// ...
<svg ref={svgRef} width={width} height={height}>
// ...
</svg>

Ensuite, nous devons ajouter un écouteur d'événement à notre élément SVG. Cela écoutera tous les mouvements de notre curseur sur le graphique.

useEffect(() => {
  const svgElement = svgRef.current;
  svgElement.addEventListener("mousemove", handleMouseMove);

  // clean up
  return () => svgElement.removeEventListener("mousemove", handleMouseMove);
}, []);

Ensuite, nous avons besoin d'une méthode pour trouver la coordonnée d'intersection entre la position du curseur et le chemin.

const getIntersectionPoint = (cursorX) => {
  // Find the segment (p1, p2) where cursorX lies between two consecutive coordinates.
  const segment = coordinates.find((p1, i) => {
    // Get the next point
    const p2 = coordinates[i + 1]; 
    // Check if cursorX falls between the two coordinates horizontally.
    return (
      p2 &&
      ((p1.x <= cursorX && p2.x >= cursorX) ||
        (p1.x >= cursorX && p2.x <= cursorX))
    );
  });

  // Return null if no valid segment is found.
  if (!segment) return null; 

  // Destructure the two coordinates in the segment.
  const [p1, p2] = [segment, coordinates[coordinates.indexOf(segment) + 1]];

  // Calculate 't' to determine the relative position between p1 and p2.
  const t = (cursorX - p1.x) / (p2.x - p1.x);

  // Interpolate the Y-coordinate using 't'.
  const y = p1.y + t * (p2.y - p1.y);

  return { x: cursorX, y };
};

Méthode de suivi des mouvements du curseur. Il utilise la méthode getIntersectionPoint pour trouver la coordonnée d'intersection actuelle.

const handleMouseMove = (event) => {
  // Get SVG position
  const svgRect = svgRef.current.getBoundingClientRect();
  // Calculate cursor's X within the SVG
  const cursorX = event.clientX - svgRect.left;

  // Find the intersection point
  const intersectionPoint = getIntersectionPoint(cursorX);
  if (intersectionPoint) {
    // Move the intersection circle to the calculated point
    circleRef.current.setAttribute("cx", intersectionPoint.x);
    circleRef.current.setAttribute("cy", intersectionPoint.y);
    circleRef.current.style.display = "block";
  }
};

Enfin, ce serait la structure de notre composant graphique

return (
  <svg ref={svgRef} height={height} width={width}>
    {drawPath()}
    {drawXAxis()}
    {drawYAxis()}
    {drawTrackingCircle()}
    {drawDataPointCircles()}
  </svg>
);

Voici comment nous pouvons utiliser notre composant Graph

<LineGraph
  width={300}
  height={400}
  coordinates={samplePoints}
  lineColor="#000"
  pathColor="#00008B"
  areaColor="#ADD8E6"
  dataPointColor="#008000"
  showFillArea
  showDataPointCircle
/>

Lien Codesandbox pour la démo LineGraph

Photo du blog par Isaac Smith sur Unsplash

Merci d'avoir lu ❤

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn