ex) 가로바 차트
import * as d3 from 'd3';
// 차트를 그리는 함수
const drawGraph = () => {
// 캔버스
const svg = d3.select('body')
.append('svg') // 가상의 캔버스를 그린다
.attr('width', 400) // 캔버스의 넓이
.attr('height', 400); // 캔버스의 높이
const data = [40, 50, 90, 100, 30, 90]; // 표현해야 할 input data
svg
.selectAll('rect') // 사각형 모양, 바 차트를 의미
.data(data) // 데이터를 집어 넣고
.enter() // 데이터를 순회한다.
.append('rect')
.attr('x', 10) // 도형을 그릴 x좌표의 값
.attr('y', (data, idx) => idx * (20 + 1)) // 도형을 그릴 y좌표의 값
.attr('width', (data) => data) // 각각의 데이터를 바 차트의 가로 길이로
.attr('height', 20) // 바 차트의 높이는 20
.attr('fill', 'tomato') // 도형에 색깔을 부여, default는 black
.attr('class', 'bar-chart') // 직접 class를 부여하여 css로 처리도 가능
}
useEffect(()=>{
drawGraph();
},[])
ex)세로 바 차트(but 거꾸로 되어있다.)
import * as d3 from 'd3';
// 차트를 그리는 함수
const drawGraph = ()=>{
// 캔버스
const svg = d3.select('body')
.append('svg') // 가상의 캔버스를 그린다
.attr('width', 400) // 캔버스의 넓이
.attr('height', 400); // 캔버스의 높이
const data = [40, 50, 90, 50, 30, 90]; // 그래프로 나오게 될 data
svg
.selectAll('rect') // 사각형 모양, 바 차트를 의미
.data(data) // 데이터를 집어 넣고
.enter() // 데이터를 순회한다.
.append('rect')
.attr('x', (d, idx) => idx * (20 + 1)) // x 좌표의 위치는 인덱스번호 * (넓이 + 여백)
.attr('width', 20) // 가로 넓이는 20 고정, 세로 바 차트
.attr('height', (data) => data) // 높이는 각 데이터 수치만큼
.attr('class', 'bar-chart')
.attr('fill', 'tomato');
}
useEffect(()=>{
drawGraph();
},[])
y좌표의 0지점이 맨 위이고 x좌표의 0지점은 맨 왼쪽이다. 따라서 (0,0) 좌표는 맨 왼쪽 위다.
ex)세로 바 차트
import * as d3 from 'd3';
// 차트를 그리는 함수
const drawGraph = ()=>{
// 캔버스
const svg = d3.select('body')
.append('svg') // 가상의 캔버스를 그린다
.attr('width', 400) // 캔버스의 넓이
.attr('height', 400); // 캔버스의 높이
const data = [40, 50, 90, 50, 30, 90]; // 그래프로 나오게 될 data
svg
.selectAll('rect') // 사각형 모양, 바 차트를 의미
.data(data) // 데이터를 집어 넣고
.enter() // 데이터를 순회
.append('rect')
.attr('x', (d, idx) => idx * (20 + 1)) // x 좌표의 위치는 인덱스번호 * (넓이 + 여백)
.attr('width', 40) // 막대의 넓이(숫자가 클수록 막대가 뚱뚱해짐)
.attr('height', (data) => data) // 높이는 각 데이터 수치만큼
.attr('class', 'bar-chart') // bar-chart라는 class를 부여
.attr('fill', 'tomato'); // tomato 색깔
.attr('y', (data) => 400 - data);
// 400은 캔버스의 높이 이고 캔버스 높이에서 각 데이터를 뺀 값을 y좌표 시작점으로 하면 거꾸로된 막대그래프를 정상적으로 위치시킬 수 있다.
}
useEffect(()=>{
drawGraph();
},[])
x축 y축의 척도를 설정하고, 막대그래프를 그린다.
막대그래프 최종
import * as d3 from 'd3';
const drawGraph = () =>{
// 캔버스의 틀을 잡는다.
const width = 400; // 넓이 400
const height = 400; // 높이 400
// svg 테두리 내부 여백 margin
const margin = { top: 40, left: 40, bottom: 40, right: 40 };
// 지정해둔 크기에 따라 캔버스를 그린다.
const svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
// 그래프로 표현할 data
const data = [
{ day: '5일전', value: 10 ,color : 'tomato'},
{ day: '4일전', value: 20 ,color : 'orange'},
{ day: '3일전', value: 30 ,color : 'blue'},
{ day: '2일전', value: 45 , color : 'yellow'},
{ day: '어제', value: 20 ,color : 'green'},
{ day: '오늘', value: 100 ,color : 'gray'},
];
// 그래프의 index
const x = d3
.scaleBand() // 값이 문자열 : scaleBand, 숫자 : scaleLinear
.domain(data.map((object) => object.day)) // 데이터의 day 값의 범위
.range([margin.left, width - margin.right]); // 출력되는 범위, 캔버스내의 좌,우 여백을 제외한 값
const y = d3
.scaleLinear() // y축 value 값은 숫자, scaleLinear
.domain([0, d3.max(data, (d) => d.value)]) // 데이터 범위 즉, 최소, 최대값 배열
.range([height - margin.bottom, margin.top]); // range는 출력되는 범위, 캔버스 상, 하 여백을 제외한 값
const xAxis = (g) => {
return g // 각 축의 문서요소들, 이후 g container를 통해 설정한 값들이 적용.
// transform 속성을 통해 원하는 만큼 x축을 이동,
// 즉, 가로 축을 설정한 바닥 여백 만큼 띄워 준다.
.attr('transform', `translate(0, ${height - margin.bottom})`)
// 바닥에 axisBottom 함수를 통해 x축을 생성,
// tickSizeOuter는 각 축에 튀어나오는 tick의 길이를 의미
.call(d3.axisBottom(x).tickSizeOuter(0));
};
const yAxis = (g) =>
g
.attr('transform', `translate(${margin.left}, 0)`)
// 동일하게 원하는 만큼 여백을 이동
// axisLeft를 통해 좌측에 y축 생성, tickValues 함수로 y축 간격을 정한다
// tickSize를 width만큼 그려 그리드 생성.
.call(d3.axisLeft(y).tickValues([0, 20, 40, 60, 80, 100]).tickSize(-width))
.call((g) => g.select('.domain').remove()) // 축을 깔끔하게 지울수도 있다.
.attr('class', 'grid'); // 이런식으로 직접 class를 부여해서 css로도 속성 부여 가능(색깔, 길이 등)
svg.append('g').call(xAxis); // x축 index 추가
svg.append('g').call(yAxis); // y축 index 추가
// selectAll을 통해 존재하지 않았던 rect 사각형 도형(막대) 선택,
// 이 후 append해서 속성, 데이터를 지정해서 최종적으로 그려준다.
svg
.selectAll('rect') // 막대(사각형 도형)
.data(data) // 데이터 선택
.enter() // 데이터를 순회
.append('rect')
.attr('x', (data) => x(data.month) + x.bandwidth() / 2 - 20)
// 막대의 넓이의 반절(20)을 뺌으로서 막대의 중앙에 x축의 달이 나오도록 한다.
// (막대의 중간에 1월,2월.. 등 x좌표의 index가 표기된다.)
.attr('y', (data) => y(data.value)) // y좌표 척도
.attr('width', 40) // 막대(도형)의 넓이 (숫자가 커지면 막대가 뚱뚱해진다)
.attr('height', (data) => y(0) - y(data.value))
.attr('class', 'bar-chart') // 클래스를 부여하여 css, scss등으로 넓이나 색깔 등을 직접 부여 가능
.attr('fill', (data) => data.color); // data에 미리 color를 넣어서 data마다 색깔 지정 가능
}
useEffect(() => {
drawGraph();
},[])