Skip to content

[Chart] Pie chart#258

Open
MarkLeemee wants to merge 11 commits intomainfrom
issue257.feat.pie_chart_default
Open

[Chart] Pie chart#258
MarkLeemee wants to merge 11 commits intomainfrom
issue257.feat.pie_chart_default

Conversation

@MarkLeemee
Copy link
Contributor

@MarkLeemee MarkLeemee commented Dec 9, 2022

구현 사항

  • Pie chart transition 및 legend 기본 렌더링 (scss 및 semantic 미적용)
  • hover 시, storek, tootip 노출
  • 항시 size를 입력받거나, px 단위의 default size가 정해진 기존 방식에서 모체 및 범례 등 사용 환경에 맞춰 사이즈 조절하여 렌더링되는 방식
  • 단, legend와 tooltip은 정보는 브라우저 환경 사이즈에 맞춰 렌더링

추가 논의 필요 사항


1. legend의 위치 및 list가 과하게 많은 경우

1-1. 덮어 씌기 + 전체 다 노출 (rechart 방식)

스크린샷 2022-12-09 오후 3 35 00 (갯수가 많아질 경우 chart의 크기가 줄어든다.)
스크린샷 2022-12-09 오후 3 36 13 (middle로 설정한 상태. chart의 위치와 크기와는 별개로 그냥 노출시킨다.)

  • rechart의 경우 사이즈나 위치, 갯수를 고려하지 않고 그냥 다 노출
  • 해당 chart를 맞는 용도로 사용하지 않았다고 판단 하는 듯

1-2. pagination 혹은 scroll

스크린샷 2022-12-09 오후 3 40 28

  • antd의 경우 특정 영역을 넘치는 경우 legend pagination 구현

2. 기본 architecture 구현 방식

2-1. legend, tooltip 등 react component를 만들어서 필요한 state를 구현하여 전달하는 방식 (예전 방식)

  • react state를 활용하기에 상태 변화 및 렌더링 컨트롤이 쉬워짐
  • 별도 state를 만들고 관리하여야 하며 react component를 활용하는 방식이기에 VD, lifecycle 등을 신경써야 함

2-2. 기본(default) element와 styled만 구현 후, 설정이나 인터렉션이 필요한 경우 d3 selection으로 접근하여 컨트롤 (현 코드 방식)

  • 기본 layout을 초기에 손쉽게 구상
  • 각 인터렉션 이벤트들을 모듈화 시키면 더 효율적

2-3. 최초 box(혹은 svg)만 구성 후 나머지 요소들은 생성하여 appending 하는 방식 (기본 라이브러리 방식들)

  • 요소 생성을 모듈화 시켜 놓으면 사실 2번 방식이란 큰 차이가 없기에 가장 좋은 방식이지 않을까 싶음
  • data가 변화하거나 새로 그릴 때, chart component 혹은 element들을 삭제하는 등 사이클을 관리해야 함

3.props 전달 방식

3-1. 각개 props 형식

  • 기능 및 옵션의 종류가 많아지면 가시성 및 관리가 어려워짐
  • rechart의 경우 chart, x축, y축, bar, legend 등 각각을 component 단위로 import 해오기에, 각 component에 각 props를 직접 내려주기에 해당 방식이 가능해짐
import {PieChart, XAxis, YAxis, Tooltip, Area, ... } from 'rechart'
<PieChart {...option} >
  <XAxis ... />
  <YAxis ... />
  <Tooltip ... />
  <Area ... />
  <Bar .../>
  // ...
</ Chart>

3-2. Object 형식

  • 라희님이 만든 단순하게 others를 묶는 느낌이 아닌, 하나의 스키마와 데이터 셋을 구성하는 느낌
  • antd의 경우 <Chart {...configObj} /> 형식으로 하나의 chart component에 옵션 obj를 풀어서 전달
const configObj = {
  data: [...fetchData],
  angleField: 'value',
  radius: 1,
  innerRadius: 0.6,
  label: {
    type: 'inner',
    offset: '-50%',
    content: '{value}',
    style: {
      textAlign: 'center',
      fontSize: 14,
      // ...
    },
    // ...
  },
 tooltip: {
  // ...
 },
  interactions: [
    {
      type: 'element-selected',
      // ...
    },
    // ...
  ],
  statistic: {
    title: false,
    content: 'AntV\nG2Plot',
    content: {
      style: {
        whiteSpace: 'pre-wrap',
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        // ....
      },
      // ...
    },
    // ...
  },
  // ...
};

<PieChart {...configObj} />

const chartBox = d3.select(`#${id}`)
const svg = chartBox.select('.svg')
const tooltipBox = chartBox.select('.tooltip-box')
const tooltipSircle = chartBox.select('.tooltip-sircle')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. sircle 은 어떤 의미로 사용된건가요? circle 의 오타인가 하여 남깁니다.

return arc(d)
}
})
}, [JSON.stringify(data)])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. 다른 props(colors, style, duration, tooltip 등)은 안들어가도 될까요

<WrapLegendItem key={`WrapLegendItem__${key}`}>
<WrapKey color={colors[idx]}>{key}</WrapKey>
<WrapValue>{value || 0}</WrapValue>
<WrapValue>{((value * 100) / totalCount).toFixed(2)}%</WrapValue>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3. legend 에 value를 노출 시킬 필요가 있을까요? 기본적으로 이름을 노출하고 필요하다면 legend 를 custom 할 수 있도록 옵션을 전달할 수 있으면 좋겠습니다.

const colorSizeDiff = _.size(data) - _.size(colors)
if (colorSizeDiff !== 0) {
_.forEach(_.range(colorSizeDiff + 1), () =>
colors.push(`#${Math.round(Math.random() * 0xffffff).toString(16)}`),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p4. 랜덤색상 말고 고정적인 default color 가 있는게 더 좋지 않을까요?

const tooltipTextBox = chartBox.select('.tooltip-text-box')

// default value
const SVG_WIDTH = svg.node().getBoundingClientRect().width - 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p4. 16은 어떤값인가요? 상수화할 수 없을까요?

Comment on lines +110 to +111
.text(`${data.key} :`)
tooltipTextBox.append('div').text(`${data.value}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3. tooltip 내용을 커스텀할 수 있는 방법은 없을까요?


useEffect(() => {
// selector
const chartBox = d3.select(`#${id}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. select 코드는 useEffect 바깥으로 빼도 괜찮지 않을까요 ..?

const SVG_WIDTH = svg.node().getBoundingClientRect().width - 16
const SVG_HEIGHT = svg.node().getBoundingClientRect().height
const MARGIN = 8
const INIT_DURATION_MS = 600
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. 상수도 바깥으로 빼도 괜찮을 것 같습니다 ~

opacity: 1;
`

const WrapSircle = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p2. WrapCircle로 수정해야할 것 같습니다 ~

}

const mouseleave = ({ target }) => {
d3.select(target).transition().duration(300).attr('stroke-width', 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. durtaion(300)에서 300도 상수처리하면 좋을 것 같습니다 ~

const tooltipTextBox = chartBox.select('.tooltip-text-box')

// default value
const SVG_WIDTH = svg.node().getBoundingClientRect().width - 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. 여기서 - 16 은 무엇을 의미할까요 ..?

return arc(d)
}
})
}, [JSON.stringify(data)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5. JSON.stringify(data)가 좋은 방법이 아니어서 이리저리 다르게 시도하고 있는데ㅜ 나중에는 대체되어야 할 것 같아요..
의존성에 이것저것 넣어버리게 되면 동작을 해야할 경우에도 그대로인 경우가 있어서 아예 의존성을 빼도 괜찮을 것 같기도 합니다..
아니면 아예 다 넣어버려야 할까요 🥲

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants