프론트엔드 데브코스 5기 TIL 64 - D3(색상척도, 범례, 모양, stack, 호)

김영현·2024년 1월 24일
0

TIL

목록 보기
76/129

서론

key함수, animation, colorize는 쉬워서 넘어갔다


색상척도

색상척도는 세가지로 나뉜다

  • 선형 색상척도(linearScale)
  • 순차적 색상척도(sequentialScale)
  • 범주형 색상척도(ordinalScale)

사실 척도부분에서 배운 세가지 척도를 활용하는거다.

순차적 색상척도

순차적 색상척도는 치역(range)대신 보간(interpolator)이 필요하다.
주어진 두 점의 선분을 연결하는 방법. 즉 두 값 사이를 점진적으로 어떻게 전환할 것인지 정해야한다.

const ipNum = d3.interpolateNumber(10,20);

ipNum(0) // 10
ipNum(1) // 20

y = x*10 + 10(최소값)의 함수를 나타낸다고 볼 수 있다. (단, x는 0이상 1이하)
색상에 관한 보간도 설정할 수 있다.

const ipNum = d3.interpolateRgb('steelblue', 'brown');

ipNum(0) // rgb(70,130,180)
ipNum(1) // rgb(165,42,42)

값을 촘촘히 나눈다면 steelblue => brown그라데이션으로 보일 것이다.
또한 다양한 타입의 보간을 제공하니 공식문서를 보자!

선형 색상척도

선형 색상척도는 단순하게 치역(range)에 색상을 넣어주면 된다.

const myColor = d3.scaleLinear()
.domain([1,10])
.range(['white', 'blue']);

범주형 색상척도

const myColor = d3.scaleOrdinal()
.domain(['A','B','C','D','E'])
.range([...색상들])

const myColor = d3.scaleOrdinal()
.domain(['A','B','C','D','E'])
.range(d3.schemaSet3) //d3에서 색상 스키마를 제공하기도 한다

범례(Legend)

범례는 보통 색상으로 구분한다. 따라서 색상척도를 이용한다.
범례는 두가지로 나뉜다

  • 범주형 범례
  • 연속성 범례

범주형 범례

색상척도중 범주형 색상척도를 이용하면 쉽다

//컬러를 생성해준다
const scale = d3.scaleOrdinal()
.domain(['blueberries','oranges','apples'])
.range(d3.schemeCategory10);

//범례 그룹을 하나 만든다. margin, 폰트 설정은 일단 넣지않음
const legendGroup = svg.append('g')

//범례를 만든다
const legend = legendGroup.selectAll('.legend')
.data(scale.domain())
.join('g')
.attr('transform', (d,i) => `translate(${i*90},${0})`) // 한 범례당 90px씩 이동

//범례에 들어가는 사각형을 만듬
const rectOfLegend = legend.append('rect')
.attr('fill', scale) // 범주형 색상척도로 만든 색상을 넣어준다

//범례의 텍스트
const textOfLegend = legend.append('text')
.attr(...x축 y축 위치지정)
.text(d=>d); //여기서 d는 scale.domain()으로 넣어준 데이터들 ['blueberries','oranges','apples'] 이다

연속성 범례

이 때는 순차적 색상척도를 사용하면 된다. 단, 눈금은 scaleLinear를 사용하면 된다 ㅎㅎ

const colorScale = d3.scaleSequential()
.domain([0,99])
.interpoltator(d3.tinerpolateYlOrRd);

const xScale = d3.scaleLinear()
.domain([0,99])
.range([margin.left, width - margin.right]);

const xAxis = d3.axisBottom(xScale)
.tickSize(15)
.tickFormat((v) => `${v}`)
.tickValues([25,50,75]);

const legendScale = legend.append('g');
legendScale.selectAll('rect')
.data(data)
.join('rect')
.attr('x', (d) => xScale(d))
//너비에 1.1~1.2배수를 주어야함. 1배수로 한다면선형적으로 이어진 rect들 사이사이 공간이 벌어져있다.
.attr('width', (width - margin.left - margin.right) / 100 * 1.2) 
.attr('fill', (d) => colorScale(d));

척도를 이용하여 점을 찍은 뒤 d3.line()메서드를 이용하여 선을 그리면 끝이다.

const line = d3.line()
.x((d) => xScale(d.date))
.y((d) => yScale(d.close));

svg.append('path')
.attr('class', 'line-path')
.attr('d', line(data));

영역

선으로 만든 그래프를 색상으로 꽉 채우는 것이다.
y0이 y값 기준선이고 y1이 최상위선이다.

const area = d3.area()
.x((d) => xScale(d.date))
.y0(y(0))
.y1((d) => yScale(d.close)); //0~y최댓값 까지 영역을 차지한다.

svg.append('path')
.attr('class', 'area-path')
.attr('d', area(data));

누적(Stack)

영역을 겹쳐서 누적되게 보여준다(지층처럼). 추측해보면 영역의 y0값을 잘 조정하면 될 것 같다.
라고 생각했는데, stack메서드가 따로 있네?😮

const data = [
  { 
    month: new Date(2018, 1, 1), 
      fruitSales:{
       apples:10, 
       bananas:20, 
       oranges:15
     } 
  },
  { 
    month: new Date(2018, 2, 1), 
      fruitSales:{
       apples:15, 
       bananas:15, 
       oranges:15
     } 
  },
   { 
    month: new Date(2018, 3, 1), 
      fruitSales:{
       apples:20, 
       bananas:25, 
       oranges:15
     } 
  },
];
const fruits = ['apples', 'bananas', 'oranges'];

const stack = d3.stack()
keys(fruits)
.value((obj,key) => obj.fruitSales[key]);

const series = stack(data);

이렇게 하고 x,y축 척도도 만들어 넣으면 날짜별로 과일이 어떻게 변하는지 볼 수있다.


호(arc)

원형그래프를 그릴때 쓰인다. 호도법할때 그 '호'다

const data = [1,1,2,3,5,8,13,21];
const arcs = d3.pie()(data); //d3.pie는 해당 값에 호의 크기를 만들어준다. 
// [{data, value, index, startAngle, endAngle, padAngle}] 이렇게 값을 제공해줌

const arc = d3.arc()
.innerRadius(40) //내부반경
.outerRadius(80) //외부반경
.startAngle(([startAngle, endAngle]) => startAngle); //시작 각
.endAngle(([startAngle, endAngle]) => endAngle); //끝 각

const n = 12;

Array.from({length:n}, (_,i) => {
	svg.append('path')
  	.attr('fill', d3.interpolateRainbow(i/n))
  	.attr('d', arc([i / n*2 * Math.PI, (i+1) / n*2 * Math.PI]));
})

마무리

  • 색상 척도에 대해 배웠다.
  • 범례에 대해 배웠다
  • 선에 대해 배웠다
  • 스택, 호에 대해 배웠다!
profile
모르는 것을 모른다고 하기

0개의 댓글