React Native 에서 차트 구현 - 2. 라인차트 옵션 기능
1. 개요
이전 글에서는 라인차트의 기본 기능을 구현해보았다.
하지만 해당 차트는 데이터를 받아서 그릴 수만 있을 뿐, 세부적인 설정을 할 수 없었다. 이 글에서는 세부적은 설정을 할 수 있도록 옵션 기능을 구현할 것이다.
2. 구현
이전 글에서 우리는 차트를 크게 네 개의 컴포넌트로 나누어 구현했다.
function LineChartBody(/* ... */) {
return (
<Fragment>
<XAxis {/* ... */} />
<YAxis {/* ... */} />
<Grid {/* ... */} />
<Lines {/* ... */} />
</Fragment>
);
}
그러니 옵션을 구현하는 것도 각 컴포넌트 별로 초점을 맞춰서 진행해보자.
2.1. <XAxis />
옵션 구현
X 축을 그릴 때 선택적으로 설정할 수 있는 것들은 무엇이 있을까? 하고 생각해보면 아래와 같은 요소들이 떠오른다.
- X 축 자체를 보이게/안보이게 하는 기능
- X 축 라인의 색상, 두께
- 틱을 보이게/안보이게 하는 기능
- 틱으로 사용될 값들의 목록
- 틱 선의 길이, 색상, 두께
- 틱 라벨의 폰트, 폰트 크기, 폰트 두께, 폰트 색상, 포메터(formatter)
이외에도 많은 요소들이 있을 수 있다. 하지만 이번 글에서는 일단 이 정도만 구현하자.
2.1.1. 옵션 타입 추가
위에서 나열한 요소들을 타입으로 작성하자.
import { ScaleTime } from "d3";
import { FontWeight } from "react-native-svg";
export type XAxisOptions = {
enabled?: boolean;
// X 축의 위치 offset
x?: number;
// X 축의 위치 offset
y?: number;
// X 축 라인 색상
lineColor?: string;
// X 축 라인 두께
lineWidth?: number;
// 틱을 보여줄지/안보여줄지 여부
showTicks?: boolean;
// 틱으로 사용될 값 혹은 값을 반환하는 함수
ticks?: Date[] | ((scale: ScaleTime<number, number, never>) => Date[]);
// 틱의 길이
tickLength?: number;
// 틱의 두께
tickWidth?: number;
// 틱의 색상
tickColor?: string;
// 틱 라벨의 폰트 크기
tickLabelSize?: number;
// 틱 라벨의 폰트
tickLabelFont?: string;
// 틱 라벨의 폰트 두께
tickLabelWeight?: FontWeight;
// 틱 라벨의 폰트 색상
tickLabelColor?: string;
// 틱 라벨의 형식 (값을 받아 틱 라벨을 반환하는 함수)
tickLabelFormatter?: (value: Date) => string;
};
2.1.2. <LineChart />
로부터 옵션 전달
좋다. 이제 이 값들을 <LineChart />
가 받을 수 있도록 한 뒤에, 받은 값을 <XAxis />
까지 건내주자.
// ...
import { XAxisOptions } from "./types";
// ...
type LineChartProps = {
// ...
xAxisOptions?: XAxisOptions;
};
function LineChart({
// ...
xAxisOptions,
}: LineChartProps) {
// ...
return (
<Svg {/* ... */}>
{loaded && (
<LineChartBody
// ...
xAxisOptions={xAxisOptions}
/>
)}
</Svg>
);
}
export default LineChart;
// ...
import { XAxisOptions } from "../types";
// ...
type LineChartBodyProps = {
// ...
xAxisOptions?: XAxisOptions;
};
function LineChartBody({
// ...
xAxisOptions,
}: LineChartBodyProps) {
return (
<Fragment>
<XAxis scale={xScale} paneBoundary={paneBoundary} {...xAxisOptions} />
<YAxis {/* ... */} />
<Grid {/* ... */} />
<Lines {/* ... */} />
</Fragment>
);
}
export default LineChartBody;
2.1.3. <XAxis />
수정
옵션을 전달했으니, <XAxis />
에서 해당 옵션을 사용하도록 구현을 수정해보자.
// ...
import { XAxisOptions } from "../types";
const DEFAULT_TICK_LENGTH = 6;
// `XAxisOptions` 타입의 속성을 모두 prop 으로 받을 수 있도록 지정해주자.
type XAxisProps = XAxisOptions & {
scale: d3.ScaleTime<number, number, never>;
paneBoundary: PaneBoundary;
};
function XAxis({
scale,
paneBoundary,
x = 0,
y = paneBoundary.y1,
enabled = true,
lineColor = "black",
lineWidth = 1,
showTicks = true,
ticks: _ticks,
tickLength = DEFAULT_TICK_LENGTH,
tickWidth = 1,
tickColor = "black",
tickLabelSize,
tickLabelFont,
tickLabelWeight,
tickLabelColor = "black",
tickLabelFormatter = dateFormat,
}: XAxisProps) {
const range = scale.range();
const ticks = !_ticks
? scale.ticks()
: typeof _ticks === "function"
? _ticks(scale)
: _ticks;
if (!enabled) {
return null;
}
return (
<G>
<Line
x1={range[0] + x}
x2={range[1] + x}
y1={y}
y2={y}
stroke={lineColor}
strokeWidth={lineWidth}
/>
{showTicks && (
<>
{ticks.map((tick) => (
<Line
key={`${tick}`}
x1={scale(tick)}
x2={scale(tick)}
y1={y}
y2={y + tickLength}
stroke={tickColor}
strokeWidth={tickWidth}
/>
))}
{ticks.map((tick) => (
<Text
key={`${tick}`}
x={scale(tick)}
y={y + tickLength + 2}
fill={tickLabelColor}
fontSize={tickLabelSize}
fontFamily={tickLabelFont}
fontWeight={tickLabelWeight}
textAnchor="middle"
alignmentBaseline="hanging"
>
{tickLabelFormatter(tick)}
</Text>
))}
</>
)}
</G>
);
}
export default XAxis;
이제는 이전 글의 코드와 달리 몇몇 소수의 값을 제외하고는 하드코딩이 사라진 것을 확인할 수 있다.
만약 여전히 하드코딩되어있는 값들 (textAnchor
, alignmentBaseline
) 도 옵션으로 지정하고 싶다면 XAxisOptions
타입에 해당하는 값을 추가한 뒤 똑같이 구현하면 된다.
2.1.4. <LineChart />
사용 시 옵션 적용 예
이제 X 축의 속성들을 <LineChart />
컴포넌트 사용자가 직접 지정할 수 있게 되었다.
<LineChart
series={dummySeries}
width="100%"
height={200}
xAxisOptions={{
enabled: true,
lineColor: "red",
lineWidth: 2,
tickLength: 15,
tickWidth: 3,
tickColor: "green",
tickLabelSize: 20,
tickLabelWeight: 100,
tickLabelFormatter: (date) => `${date.getMonth() + 1}.${date.getDate()}`,
}}
/>
2.2. <YAxis />
옵션 구현
그럼 이제 Y 축도 수정해보자.
Y 축도 X 축처럼 옵션으로 할만한 요소들을 생각해보자.
- Y 축 자체를 보이게/안보이게 하는 기능
- Y 축 라인의 색상, 두께
- 틱을 보이게/안보이게 하는 기능
- 틱으로 사용될 값들의 목록
- 틱 선의 길이, 색상, 두께
- 틱 라벨의 폰트, 폰트 크기, 폰트 두께, 폰트 색상, 포메터(formatter)
나열하고보니 X 축의 옵션과 거의 동일해보인다. 이렇다면 2.1.1. 에서 만든 XAxisOptions
와 공통의 상위 타입을 만든 다음에 상속 받는 식으로 만들어도 괜찮을 것 같다.
2.2.1. 옵션 타입 추가 및 수정
// - `XAxisOptions` 를 `AxisOptions` 로 바꾸고
// 몇몇 타입들을 generic 하게 받을 수 있도록 변경했다
export type AxisOptions<Scale, Value> = {
enabled?: boolean;
x?: number;
y?: number;
lineColor?: string;
lineWidth?: number;
showTicks?: boolean;
ticks?: Value[] | ((scale: Scale) => Value[]);
tickLength?: number;
tickWidth?: number;
tickColor?: string;
tickLabelSize?: number;
tickLabelFont?: string;
tickLabelWeight?: FontWeight;
tickLabelColor?: string;
tickLabelFormatter?: (value: Value) => string;
};
// - `XAixsOptions` 의 역할을 하는 `TimeAxisOptions`
// - 왜 이름이 바뀌었냐면 나중에 상황에 따라 Y 축이 시계열이 될 수도 있겠다는 생각이 들어서
// 유연하게 사용하려는 의도이다.
export type TimeAxisOptions = AxisOptions<
ScaleTime<number, number, never>,
Date
>;
// `YAxis` 의 옵션 타입으로 쓰일 `LinearAxisOptions`
export type LinearAxisOptions = AxisOptions<
ScaleLinear<number, number, never>,
number
>;
2.2.2. <LineChart />
로부터 옵션 전달
<LineChart />
로부터 <YAxis />
까지 옵션을 전달하는 것은 2.1.2. 와 거의 동일하다. 2.1.2. 혹은 3.1. 을 참고하자.
2.2.3. <YAxis />
수정
<YAxis />
구현 자체도, 2.1.3. 의 <XAxis />
와 대동소이 하다.
import { LinearAxisOptions } from "../types";
const DEFAULT_TICK_LENGTH = 6;
// `LinearAxisOptions` 타입의 속성을 모두 prop 으로 받을 수 있도록 지정해주자.
type YAxisProps = LinearAxisOptions & {
scale: d3.ScaleLinear<number, number, never>;
paneBoundary: PaneBoundary;
};
function YAxis({
scale,
paneBoundary,
x = paneBoundary.x1,
y = 0,
enabled = true,
lineColor = "black",
lineWidth = 1,
showTicks = true,
ticks: _ticks,
tickLength = DEFAULT_TICK_LENGTH,
tickWidth = 1,
tickColor = "black",
tickLabelSize,
tickLabelFont,
tickLabelWeight,
tickLabelColor = "black",
tickLabelFormatter = (val) => `${val}`,
}: YAxisProps) {
const range = scale.range();
const ticks = !_ticks
? scale.ticks()
: typeof _ticks === "function"
? _ticks(scale)
: _ticks;
if (!enabled) {
return null;
}
return (
<G>
<Line
x1={x}
x2={x}
y1={range[0] + y}
y2={range[1] + y}
stroke={lineColor}
strokeWidth={lineWidth}
/>
{showTicks && (
<>
{ticks.map((tick) => (
<Line
key={`${tick}`}
x1={x - tickLength}
x2={x}
y1={scale(tick)}
y2={scale(tick)}
stroke={tickColor}
strokeWidth={tickWidth}
/>
))}
{ticks.map((tick) => (
<Text
key={`${tick}`}
x={x - tickLength - 2}
y={scale(tick)}
fill={tickLabelColor}
fontSize={tickLabelSize}
fontFamily={tickLabelFont}
fontWeight={tickLabelWeight}
textAnchor="end"
alignmentBaseline="middle"
>
{tickLabelFormatter(tick)}
</Text>
))}
</>
)}
</G>
);
}
export default YAxis;
이제는 이전 글의 코드와 달리 몇몇 소수의 값을 제외하고는 하드코딩이 사라진 것을 확인할 수 있다.
만약 여전히 하드코딩되어있는 값들 (textAnchor
, alignmentBaseline
) 도 옵션으로 지정하고 싶다면 LinearAxisOptions
타입에 해당하는 값을 추가한 뒤 똑같이 구현하면 된다.
2.2.4. <LineChart />
사용 시 옵션 적용 예
이제 Y 축의 속성들을 <LineChart />
컴포넌트 사용자가 직접 지정할 수 있게 되었다.
<LineChart
series={dummySeries}
width="100%"
height={200}
yAxisOptions={{
enabled: true,
lineColor: "brown",
lineWidth: 3,
tickLength: 2,
tickWidth: 3,
tickColor: "yellow",
tickLabelSize: 8,
tickLabelWeight: 700,
tickLabelFormatter: (val) => val.toLocaleString(),
}}
/>
2.3. <Grid />
옵션 구현
<Grid />
의 옵션을 구현하기 위해 코드를 천천히 살펴보다가 이런 의문이 생겼다.
"지금까지 구현했던 차트들을 떠올려보면 그리드 라인은 보통 별개로 존재하지 않는다. X 축 혹은 Y 축의 틱과 값을 공유한다. 왜냐하면 사용자 입장에서 그리드 라인에 해당하는 값 혹은 날짜가 무엇인지 알고 싶은데, 이것을 따로 표시하기보다는 X,Y 축에 표시하는 것이 일관성 있기 때문이다."
"아니 그 이전에, 그리드라인의 태생이 X,Y 축의 틱의 연장선인게 아닌가? 내가 너무 생각 없이 축과 그리드라인을 분리해서 생각한 것이 아닐까?"
의문을 해결하기 위해, 이럴 때 레퍼런스로 많이 활용하는 highcharts 의 데모 및 API 문서와 D3.js 의 예제들을 살펴보았다. 살펴 본 결과, 내가 잘못 생각하고 있던 게 맞았다는 걸 깨달았다.
따라서 <Grid> />
컴포넌트는 삭제 하고, 해당 컴포넌트의 기능을 <XAxis />
와 <YAxis />
에 편입시켰다. 이제 그리드 라인을 활성화/비활성화하기 위해서는 <Grid />
컴포넌트를 사용하는 것이 아니라 <XAxis />
, <YAxis />
의 옵션으로 설정해야 한다.
2.3.1. 옵션 타입 수정
TimeAxisOptions
, LinearAxisOptions
의 부모인 AxisOptions
에 그리드 라인 관련 속성을 추가하자.
export type AxisOptions<Scale, Value> = {
// ...
// 그리드 라인을 보여줄지/안보여줄지 여부
showGridLines?: boolean;
// 그리드 라인의 두께
gridLineWidth?: number;
// 그리드 라인의 색상
gridLineColor?: string;
};
2.3.2. <XAxis />
, <YAxis />
수정
위에서 추가한 옵션들을 사용해 <XAxis />
에 그리드 라인을 그리자.
// ...
function XAxis({
// ...
showGridLines = false,
gridLineWidth = 1,
gridLineColor = "lightgray",
}: XAxisProps) {
// ...
return (
<G>
{/* ... */}
{showGridLines &&
ticks.map((tick) => (
<Line
key={`${tick}`}
x1={scale(tick)}
x2={scale(tick)}
y1={paneBoundary.y1}
y2={paneBoundary.y2}
stroke={gridLineColor}
strokeWidth={gridLineWidth}
/>
))}
</G>
);
}
(<YAxis />
도 코드가 거의 동일하므로 해당 코드는 생략한다.)
2.3.3. <LineChart />
사용 시 옵션 적용 예
이제 그리드 라인도 자유롭게 변경할 수 있다.
<LineChart
series={dummySeries}
width="100%"
height={200}
xAxisOptions={{
showGridLines: true,
gridLineWidth: 2,
gridLineColor: "rgba(0, 0, 0, 0.2)",
}}
// Y 축의 `showGridLines` 은 기본값이 `true`이다.
// 보편적으로 Y 축의 그리드라인은 그리는 편이 많다는 (자의적인) 판단에 의해서다.
yAxisOptions={{
showGridLines: false,
}}
/>
2.4. <Lines />
옵션 구현
<Lines />
는 옵션을 적용하는 방식이 다른 컴포넌트에 비해 하나 더 존재한다. 바로 series
에 옵션 값을 받는 방법이다.
왜냐하면 <LineChart />
는 series
에 데이터를 배열로 받아 여러 개의 라인을 그릴 수 있는데, 이 경우 라인들 전체에 대한 공통적인 옵션을 지정할 수도 있지만 그 중 특정 라인에 대해서만 별도의 옵션을 지정하고 싶을 수도 있기 때문이다.
예를 들어, 네 개의 라인이 그려지는 차트인데 그 중 하나가 특히 중요한 값이라 해당 시리즈의 라인만 굵게 표시하거나 특히 더 밝은 색상으로 표시하고 싶을 수 있다.
따라서 라인들 전체에 공통으로 적용할 옵션은 다른 컴포넌트들처럼 <LineChart />
에서 옵션(linesOptions
)을 받을 것이며, 특정 라인에만 적용할 옵션은 series
에 받을 것이다.
2.4.1. 옵션 타입 추가 및 수정
그러면 series
의 타입을 수정하고, 별도의 옵션 타입도 추가해보자.
export type TimeSeries = {
// 이 시리즈의 라인의 색상을 지정할 수 있다.
color?: string;
// 이 시리즈의 라인의 굵기를 지정할 수 있다.
lineWidth?: number;
data: { date: Date; value: number }[];
};
export type LinesOptions = {
// - 라인에 적용될 색상을 배열로 받는다.
// - 배열에 들어간 순서대로 라인에 색상이 적용된다.
colors?: string[];
// - 라인의 굵기는 단일값을 받는다.
// - 만약 `colors` 처럼 배열로 받아서 차례로 지정하고 싶다면 그렇게 수정해도 된다.
// - 다만 여기서는 선 굵기는 일일이 지정하는 경우가 적고,
// 일일이 지정하고 싶다면 `TimesSeries`에 지정하는 게 편할 것이라는 (자의적인) 판단에 의해 단일값을 받는다.
lineWidth?: number;
};
2.4.2. <LineChart />
로부터 옵션 전달
<LineChart />
로부터 <Lines />
까지 옵션을 전달하는 것은 2.1.2. 와 거의 동일하다. 2.1.2. 혹은 3.1. 을 참고하자.
2.4.3. <Lines />
수정
<Lines />
의 옵션 적용 방식은 <XAxis />
, <YAxis />
와 약간 다르다. series
에 적용된 옵션값이 있으면 해당 값을 먼저 적용한 뒤에, linesOptions
로 받은 값들을 적용해야 한 다.
import { G, Path } from "react-native-svg";
import { LinesOptions, TimeSeries } from "../types";
const DEFAULT_COLORS = [
'blue',
'skyblue',
'green',
'brown',
'gray',
'orange',
'purple',
'red',
'pink',
'black',
];
type LinesProps = LinesOptions & {
series: TimeSeries[];
lineFunc: d3.Line<TimeSeries["data"][0]>;
};
function Lines({
series,
lineFunc,
colors = DEFAULT_COLORS,
lineWidth = 1,
}: LinesProps) {
return (
<G>
{series.map((sr, i) => (
<Path
key={i}
d={lineFunc(sr.data) ?? undefined}
// series.color 를 먼저 확인하고 해당 값이 없으면 colors 로부터 색상 값을 가져온다.
stroke={sr.color ?? colors[i % colors.length]}
strokeLinecap="round"
fill="transparent"
// series.lineWidth 를 먼저 확인하고 해당 값이 없으면 lineWidth 로부터 굵기 값을 가져온다.
strokeWidth={sr.lineWidth ?? lineWidth}
/>
))}
</G>
);
}
export default Lines;
2.4.4. <LineChart />
사용 시 옵션 적용 예
이제 라인의 색상 및 굵기를 컴포넌트 사용자가 직접 지정할 수 있게 되었다.
<LineChart
series={dummySeries}
width="100%"
height={200}
xAxisOptions={{ showTicks: false, showGridLines: true }}
yAxisOptions={{ showTicks: false, showGridLines: true }}
linesOptions={{
colors: ["red", "orange", "green", "blue"],
lineWidth: 2,
}}
/>
시리즈 별로 별도의 색상 혹은 굵기를 지정하는 것도 가능하다.
const dummySeriesWithCustom = [...dummySeries.map((sr) => ({ ...sr }))];
dummySeriesWithCustom[0].color = "black";
dummySeriesWithCustom[0].lineWidth = 4;
// ...
<LineChart
series={dummySeriesWithCustom}
width="100%"
height={200}
xAxisOptions={{ showTicks: false, showGridLines: true }}
yAxisOptions={{ showTicks: false, showGridLines: true }}
linesOptions={{
colors: ["red", "orange", "green", "blue"],
lineWidth: 2,
}}
/>;
2.5. paneBoundary
관련 옵션 구현
바로 위 2.4.4. 에 그려진 라인차트를 보면 이상함을 느낄 수 있다.
X 축, Y 축의 틱을 모두 비활성화했는데 해당 영역까지 차트가 그려지는 게 아니라 여백으로 남아있는 걸 볼 수 있다.
틱의 유무를 판단해서 자동으로 여백이 계산되면 좋겠지만, 틱 및 틱라벨의 크기는 여러가지 변수가 많기도 하고 (틱의 길이, 틱라벨의 문자열 길이, 폰트 스타일 등) 틱의 크기와 별개로 사용자가 여백을 지정하고 싶을 수 있기 때문에, 자동으로 계산되게 하는 것보다는 사용자가 지정하게 하는 것이 나을 수도 있다.
그래서 여기서는 여백을 옵션으로 지정할 수 있게 하겠다. <LineChart />
에서 paneBoundary
에 값을 넣어줄 때 하드코딩했던 여백들을 옵션으로 지정할 수 있게끔 할 것이다.
2.5.1. 옵션 타입 추가
export type PaneOptions = {
// 상하좌우에 모두 적용되는 여백.
// 만약 각 방향에 대한 여백값이 따로 지정되면 이 값은 무시된다.
margin?: number;
// 상단의 여백.
// `margin` 이 지정되어 있더라도 이 값을 지정하면 이 값이 우선적으로 적용된다.
marginTop?: number;
// 왼쪽의 여백.
// `margin` 이 지정되어 있더라도 이 값을 지정하면 이 값이 우선적으로 적용된다.
marginLeft?: number;
// 오른쪽의 여백.
// `margin` 이 지정되어 있더라도 이 값을 지정하면 이 값이 우선적으로 적용된다.
marginRight?: number;
// 하단의 여백.
// `margin` 이 지정되어 있더라도 이 값을 지정하면 이 값이 우선적으로 적용된다.
marginBottom?: number;
};
2.5.2. <LineChart />
수정
이 옵션의 경우 하위 컴포넌트로 전달해줄 필요가 없이 <LineChart />
에서 바로 사용하면 된다.
type LineChartProps = {
// ...
paneOptions?: PaneOptions;
};
function LineChart({
// ...
paneOptions = {},
}: LineChartProps) {
// ...
const { margin, marginTop, marginLeft, marginRight, marginBottom } =
paneOptions || {};
// `paneOptions` 의 값들을 활용해 `paneBoundary` 값을 계산한다.
const updatePaneBoundary = (width?: number, height?: number) => {
setState(dr => {
if (width !== undefined) {
dr.width = Math.round(width);
}
if (height !== undefined) {
dr.height = Math.round(height);
}
dr.paneBoundary = new PaneBoundary({
x1: marginLeft ?? margin ?? DEFAULT_Y_AXIS_WIDTH,
x2: dr.width - (marginRight ?? margin ?? 10),
y1: dr.height - (marginBottom ?? margin ?? DEFAULT_X_AXIS_HEIGHT),
y2: marginTop ?? margin ?? 10,
});
});
};
// `paneOptions` 의 여백 값이 하나라도 바뀌면 `updatePaneBoundary()` 를 호출한다.
useEffect(() => {
if (!state.width || !state.height) {
return;
}
updatePaneBoundary();
}, [margin, marginTop, marginLeft, marginRight, marginBottom]);
// `onLayout` 이벤트 리스너가 실행되면 `updatePaneBoundary()` 를 호출한다.
const onLayout: SvgProps['onLayout'] = evt => {
const { layout } = evt.nativeEvent;
updatePaneBoundary(layout.width, layout.height);
};
// ...
return (
// ...
);
}
export default LineChart;
2.5.3. <LineChart />
사용 시 옵션 적용 예
<LineChart
series={dummySeries}
width="100%"
height={200}
xAxisOptions={{ showTicks: false, showGridLines: true }}
yAxisOptions={{ showTicks: false, showGridLines: true }}
paneOptions={{ margin: 4 }}
/>
이제 차트가 약간의 여백만 가지도록 그려진다.
3. 결과
이로서 라인차트의 옵션 기능을 구현해보았다. <LineChart />
컴포넌트 사용자는 요구사항이나 취향에 따라 차트를 다양한 형식으로 사용할 수 있게 되었다.
위에서 제공하는 옵션 항목들은 어디까지나 예시일 뿐, 개발자의 취향에 따라 몇몇 항목은 제외할 수도 있고 몇몇 항목은 추가할 수도 있다.
예를 들어 X 축의 라벨 위치를 조정하는 offset 을 옵션으로 넣고 싶다면 AxisOptions
에 tickLabelOffsetX
등의 값을 추가할 수 있을 것이다.
3.1. 상세 코드 전문
본문에 삽입된 코드들은 생략된 부분들이 있으므로 코드 전문을 보고 싶다면 아래 링크를 참고하자.
3.2. 실행해보기
구현 결과를 실기기 혹은 에뮬레이터에서 직접 확인하고 싶다면 https://github.com/ricale/D3ChartExamples 에서 프로젝트를 받아서 실행해보면 된다.
# 안드로이드
git clone https://github.com/ricale/D3ChartExamples.git
cd ./D3ChartExamples
yarn
yarn android
# iOS
git clone https://github.com/ricale/D3ChartExamples.git
cd ./D3ChartExamples
yarn
cd ./ios && pod install && cd ../
yarn ios
4. 다음
다음에 구현 및 정리할 예정인 작업들은 아래와 같다.
- 라인차트 레전드 기능 구현
- 라인차트 특정 아이템 선택 기능 구현 (터치 이벤트 활용)
- 라인차트 애니메이션 기능 구현 (초기화 시, 값 변경 시 등)
- 컬럼차트 구현 (상세 계획 미정)
- 파이차트 구현 (상세 계획 미정)