React, Next에서 i18next를 사용해서 언어셋 설정하기
2023-10-28
D3.js 를 사용하여 데이터 시각화하기 #2 Bar Charts
2018-10-30
Explanation
선 그래프에 이어서, 오늘은 막대 그래프 예제 코드를 보면서 D3.js와 API들을 알아보려 합니다.
설명 부분이 저번 글과 겹치는 부분은 생략하려 합니다, 이해가 안되시는 분은 이전 글을 먼저 살짝 보시고 오는게 좋을거 같아요.
이전글 : D3.js 를 사용하여 데이터 시각화하기 #1 Line Charts
오늘은 2일차이기 때문에 글에는 수많은 추측과 오류를 담고 있습니다.
예제 코드 출처
https://beta.observablehq.com/@mbostock/d3-bar-chart
아래의 코드는 위 예제 코드를 아주 조금 수정한 내용입니다.
이번 글에는 바로 코드에 주석으로 이야기를 적도록 하겠습니다.
1 2 3 4 5 6 7 8 9 10 |
<!doctype html> <html lang="ko"> <head> <title>D3 bar chart example</title> <script src="https://d3js.org/d3.v5.min.js"></script> </head> <body> <script src="bar-chart.js"></script> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
// bar-chart.js // line chart와 동일 const width = 500; const height = 500; const margin = {top: 40, left: 40, bottom: 40, right: 40}; const data = [ {name: 'a', value: 10}, {name: 'b', value: 29}, {name: 'c', value: 32}, {name: 'd', value: 25}, {name: 'e', value: 23}, {name: 'f', value: 15} ]; const x = d3.scaleBand() // .scaleBand() 그래프의 막대의 반복되는 범위를 정해줍니다. .domain(data.map(d => d.name)) // .domain() 각각의 막대에 순서대로 막대에 매핑합니다. .range([margin.left, width - margin.right]) // 시작위치와 끝 위치로 눈금의 범위를 지정합니다. .padding(0.2); // 막대의 여백을 설정합니다. // line chart와 동일 const y = d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]).nice() .range([height - margin.bottom, margin.top]); // line chart와 동일 const xAxis = g => g .attr('transform', `translate(0, ${height - margin.bottom})`) .call(d3.axisBottom(x) .tickSizeOuter(0)); // line chart와 동일 const yAxis = g => g .attr('transform', `translate(${margin.left}, 0)`) .call(d3.axisLeft(y)) .call(g => g.select('.domain').remove()); // line chart와 동일 const svg = d3.select('body').append('svg').style('width', width).style('height', height); svg.append('g').call(xAxis); svg.append('g').call(yAxis); svg.append('g') .attr('fill', 'steelblue') .selectAll('rect').data(data).enter().append('rect') // .selectAll() | .select() 메서드는 해당 엘리먼트를 찾지만, 가상의 요소로 선택되기도 합니다. // .data() 앞에 선택된 select에 (data)배열에 Join하여 새 선택항목을 반환합니다. // DOM에 없는 선택된 엘리먼트에 각 데이터에 대한 자리의 노드를 반환합니다. // 여기까지의 코드를 간략하게 풀어보면 // svg에 g 엘리먼트를 추가하고 그 안의 rect 엘리먼트를 찾습니다. // 새로 추가된 g 엘리먼트이기 때문에 그 안의 rect 엘리먼트는 없기 때문에 가상의 엘리먼트로 선택되었습니다. // .data(data)로 가상의 엘리먼트에 data 배열 데이터와 Join 되고 // .enter() Join 된 데이터에 각 자리에 대한 노드를 반환하고 // .append() 반환된 노드 데이터를 담고 react 엘리먼트를 추가합니다. // ex. data = [1, 2, 3, 4] 값을 가지고 있었다면 1, 2, 3, 4 데이터와 매핑된 rect 엘리먼트가 4개 추가됩니다. .attr('x', d => x(d.name)) .attr('y', d => y(d.value)) .attr('height', d => y(0) - y(d.value)) .attr('width', x.bandwidth()); // .bandwidth() 이름 그대로 막대기의 너비값을 응답합니다. // 인자값으로 명칭된 d가 svg 엘리먼트 속성 d를 의미하는 줄 알았는데, 그냥 data 값을 의미하는 듯 합니다. svg.node(); // 실행? |
예제를 두개 정도 해보니까 조금은 D3.js에 대해 익숙해지는 듯??? 합니다? 그리고 몇가지 수정을 해볼수록 D3.js는 지금 제가 아는 것보다 훨씬 다양한 용도로 사용되겠지만 일단 차트를 그림에 있어서는 SVG에 대한 이해가 많을 수록 도움이 될거 같아요. 그리고 D3.js는 SVG를 조금 더 쉽게 그릴 수 있는 라이브러리 같다는 느낌이 들었어요. 그리고 다음 시간은 파이 차트입니다!!