본문 바로가기

오픈소스/노드

[Node] React 정리(28) - D3와 접목 (1)

요즘은 다양한 차트 라이브러리들이 정말 많은 기능들을 제공해줘서 편리하게 사용할 수 있었습니다. 리액트와 D3를 이용하여 그래프를 생성할 때는 특별한 차이가 있습니다.

 

D3는 DOM을 직접 제어하고 React는 Virtual DOM으로 제어하기 때문에 리액트를 이용하여 D3를 사용하게 될 경우 사람마다 사용방법이 많이 갈린다고 합니다.

 

여기서 가장 일반적으로 사용되는 방법은 DOM은 React에게, 계산은 D3에게하게 두는 것입니다. SVG path 계산, scale, layouts, transformations 등의 선/도형등의 모양을 계산하는 것만 D3가 하게하고 나머지는 React에게 맡기게 되면 다음과 같은 장점을 얻게됩니다.

 

장점

  • 가장 React-지향적
  • 이미 있는 다른 React 코드와도 가장 잘 어울림 (React 개발자들이 제일 좋아하는 방법)
  • SSR 가능, React Native 혹은 React VR로 넘길 수 도 있음

 

본격적으로 리액트와 D3를 사용하여 간단하게 코드를 짜보도록 하겠습니다.

 

# Contents


  • line Graph
  • line Curve

 

 

# line Graph


먼저 라이브러리를 설치하고, 사용법을 알아보도록 하겠습니다.

 

라이브러리를 아래 명령어를 통해 설치합니다.

npm install --save d3

 

먼저 예제코드를 보도록 하겠습니다. 

 

import { select, line } from "d3";
import React, { useEffect, useRef, useState } from "react";

export default function MyLineGraph() {
    const [data, setData] = useState([10, 20, 40, 30]);
    const svgRef = useRef(null);

    useEffect(() => {
        const svg = select(svgRef.current);

        const myLine = line()
            .x((value, index) => index * 50)
            .y((value) => 200 - value);

        svg.selectAll("path")
            .data([data])
            .join((enter) => enter.append("path"))
            .attr("d", (value) => myLine(value))
            .attr("fill", "none")
            .attr("stroke", "red");
    }, [data]);

    return (
        <>
            <svg ref={svgRef} xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" version="1.1"></svg>
        </>
    );
}

 

select 객체를 생성하여 Ref.current에 담은 svg 변수를 만들고, line 함수를 만들어 svg변수 안에 line 함수와 데이터, enter를 path로 등록하여 결과를 뿌려주었습니다. path의 속성과 예제는 아래와 같습니다.

 

PATH 의 속성은 다음과 같습니다.

  • MoveTo: M, m
  • LineTo: L, l, H, h, V, v
  • Cubic Bézier Curve: C, c, S, s
  • Quadratic Bézier Curve: Q, q, T, t
  • Elliptical Arc Curve: A, a
  • ClosePath: Z, z

 

Move

M : 현재 점을 좌표 x, y로 이동합니다.

 

m : 경로의 마지막 알려진 위치를 x축을 따라 dx만큼 이동하고 y축을 따라 dy만큼 이동하여 현재 점을 이동합니다.

 

Line : line, horizontal, vertical

L : 현재 점에서 x,y로 지정된 끝점까지 선을 그립니다.

l : 현재 지점에서 끝 지점까지 선을 그립니다.

H : 현재 지점에서 끝 지점까지 수평선을 그립니다.

h : 현재 지점에서 끝 지점까지 수평선을 그립니다.

V : 현재 지점에서 끝 지점까지 수직선을 그립니다.

v : 현재 지점에서 끝 지점까지 수직선을 그립니다.

 

좀 예시를 들어서 구체적으로 확인해봅시다.

<path d="M 10,10 l 80,80 v -80 h -40" stroke="blue" fill="none"></path>

10, 10 까지 이동(시작)

현재 좌표에서 80, 80만큼 이동 (웹 상에서는 반전되어 보인다)

현재 좌표에서 수직 -80만큼 이동

현재 좌표에서 수평 -40만큼 이동

 

 

 

# line Curve


라인을 그린 함수에 Curve 메소드와 CurveBasis를 임포트하여 넣어주면 간단하게 이용할 수 있습니다.

 

import { select, line, curveBasis } from "d3";
import React, { useEffect, useRef, useState } from "react";

export default function MyLineGraph() {
    const [data, setData] = useState([10, 20, 40, 30]);
    const svgRef = useRef(null);

    useEffect(() => {
        const svg = select(svgRef.current);

        const myLine = line()
            .x((value, index) => index * 50)
            .y((value) => 200 - value)
            .curve(curveBasis);

        svg.selectAll("path")
            .data([data])
            .join((enter) => enter.append("path"))
            .attr("d", (value) => myLine(value))
            .attr("fill", "none")
            .attr("stroke", "red");
    }, [data]);

    return (
        <>
            <svg ref={svgRef} xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" version="1.1"></svg>
        </>
    );
}