개발/Javascript
[Javscript/Rechart] x축 스크롤링 추가
이나당
2025. 5. 3. 16:57
const CustomTick = (props) => {
const { x, y, payload } = props
const dateParts = payload.value.split('-') // ["2024", "12", "15"]
return (
<text
x={x}
y={y}
textAnchor="front"
fontSize={12}
letterSpacing={-0.55}
fontWeight={500}
fill="#333"
>
<tspan x={x} dy="12">
{dateParts[0]}년
</tspan>
<tspan x={x} dy="15">
{dateParts[1]}월 {dateParts[2]}일
</tspan>
</text>
)
}
const StatUsageStatus = ({ value }) => {
...코드생략
// x축 간격 조정 (4rem)
const chartWidth =
Math.max(chartData?.length * 64, 800) >=
document?.querySelector('.ChartWrap')?.offsetWidth
? Math.max(chartData?.length * 64, 800)
: '100%'
return (
<StatTabPanel value={value} index={0} className="StatUsageStatus">
...코드생략
<Box className="ChartBox">
<Box className="ChartContent">
<ResponsiveContainer width={chartWidth} height="100%">
<AreaChart
width={'100%'}
height={500}
data={chartData}
margin={{
top: 10,
right: 60,
left: 0,
bottom: 30,
}}
>
{/* ✅ SVG 그라데이션 정의 */}
<defs>
{/* userCount 그래디언트 */}
<linearGradient
id="userCountGradient"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop offset="0%" stopColor="#f1bd44" stopOpacity={0.5} />
<stop offset="100%" stopColor="#f1bd44" stopOpacity={0} />
</linearGradient>
<linearGradient
id="preReviewCountGradient"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop offset="0%" stopColor="#53a9eb" stopOpacity={0.5} />
<stop offset="100%" stopColor="#53a9eb" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis
dataKey="date"
interval={0}
tick={<CustomTick />}
tickLine={false}
/>
<YAxis stroke="#333" tickLine={false} />
<Tooltip />
<Area
dataKey="preReviewCount"
dot={{ strokeWidth: 2, r: 1 }}
fill="url(#preReviewCountGradient)"
name="테스트수"
stroke="#53a9eb"
/>
<Area
dataKey="userCount"
dot={{ strokeWidth: 2, r: 1 }}
fill="url(#userCountGradient)"
name="이용자 수"
stroke="#f1bd44"
/>
</AreaChart>
</ResponsiveContainer>
</Box>
<Box className="ChartLegends">
<Box className="ChartLegend">
<Box />
<T>이용자 수</T>
</Box>
<Box className="ChartLegend">
<Box />
<T>테스트수</T>
</Box>
</Box>
</Box>
</StatTabPanel>
)
}
export { StatUsageStatus }
처음엔 전체 가로스크롤 되는 코드였는데, 디자인상으로는 길어지면 y축은 고정이고 x축만 스크롤이 되게 디자인이 나와있어서, 코드를 수정했다. 처음에 어떻게 할지 고민했는데 해당 라이브러리 깃 issue에 비슷한 고민 해결을 올려둔 분이 있어서 참고할 수 있었다.
const StatUsageStatus = ({ value }) => {
...코드생략
return (
<StatTabPanel value={value} index={0} className="StatUsageStatus">
<Box className="ChartWrap">
... 코드생략
<Box className="ChartBox">
<Box className="ChartContent">
<Box className="ChartYAxis">
<AreaChart
width={62}
height={400}
data={chartData}
margin={{
top: 10,
right: 0,
left: 0,
bottom: 65,
}}
>
<YAxis stroke="#333" tickLine={false} />
<Area
fillOpacity={0}
strokeOpacity={0}
dataKey="preReviewCount"
/>
<Area fillOpacity={0} strokeOpacity={0} dataKey="userCount" />
</AreaChart>
</Box>
<Box className="ChartXAxis">
<ResponsiveContainer width={chartWidth} height="100%">
<AreaChart
width={'100%'}
height={400}
data={chartData}
margin={{
top: 10,
right: 60,
left: 0,
bottom: 30,
}}
>
{/* SVG 그라데이션 정의 */}
<defs>
{/* userCount 그래디언트 */}
<linearGradient
id="userCountGradient"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop offset="0%" stopColor="#f1bd44" stopOpacity={0.5} />
<stop offset="100%" stopColor="#f1bd44" stopOpacity={0} />
</linearGradient>
<linearGradient
id="preReviewCountGradient"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop offset="0%" stopColor="#53a9eb" stopOpacity={0.5} />
<stop offset="100%" stopColor="#53a9eb" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis
dataKey="date"
interval={0}
tick={<CustomTick />}
tickLine={false}
/>
<Tooltip />
<Area
dataKey="preReviewCount"
dot={{ strokeWidth: 2, r: 1 }}
fill="url(#preReviewCountGradient)"
name="테스트수"
stroke="#53a9eb"
/>
<Area
dataKey="userCount"
dot={{ strokeWidth: 2, r: 1 }}
fill="url(#userCountGradient)"
name="이용자 수"
stroke="#f1bd44"
/>
</AreaChart>
</ResponsiveContainer>
</Box>
</Box>
<Box className="ChartLegends">
<Box className="ChartLegend">
<Box />
<T>이용자 수</T>
</Box>
<Box className="ChartLegend">
<Box />
<T>테스트수</T>
</Box>
</Box>
</Box>
</Box>
</StatTabPanel>
)
}
// recharts라이브러리 스타일
.ChartContent {
display: flex;
height: dp(400);
.ChartYAxis {
width: dp(80);
height: dp(400);
}
.ChartXAxis {
overflow: hidden;
overflow-x: auto;
&::-webkit-scrollbar {
height: dp(6);
}
&::-webkit-scrollbar-thumb {
border-radius: dp(3);
background: #aaa;
}
&::-webkit-scrollbar-thumb:hover {
background: #aaa;
}
&::-webkit-scrollbar-track {
background: #eee;
}
.recharts-responsive-container {
.recharts-wrapper {
.recharts-surface {
// 차트 내 가로선
.recharts-cartesian-grid {
.recharts-cartesian-grid-horizontal {
line {
stroke: #ddd;
stroke-dasharray: 2 2;
}
}
}
// 차트 내 도트
.recharts-area {
&:first-child {
.recharts-area-dots {
circle {
stroke: #0b7cd3;
}
}
}
&:last-child {
.recharts-area-dots {
circle {
stroke: #d3970b;
}
}
}
}
// 차트 내 X축
.recharts-xAxis {
.recharts-cartesian-axis-line {
stroke: #ddd;
stroke-width: dp(1);
stroke-dasharray: 2 2;
}
.recharts-cartesian-axis-ticks {
.recharts-cartesian-axis-tick {
text-align: left;
@include font(500, 12, 20, -0.55);
}
}
}
// 차트 내 Y축
.recharts-yAxis {
.recharts-cartesian-axis-line {
stroke: #aaa;
}
.recharts-cartesian-axis-ticks {
@include font(bold, 14, 20);
}
}
}
.recharts-tooltip-wrapper {
.recharts-default-tooltip {
padding: dp(5) dp(10) dp(10) !important;
.recharts-tooltip-label {
@include font(600, 14, 24);
}
.recharts-tooltip-item-list {
.recharts-tooltip-item {
padding: 0 !important;
span {
@include font(bold, 14, 20);
}
}
}
}
}
}
}
}
}
Y축과 X축을 따로 분리하고 X축만 스크롤이 생기도록 div를 분리했다.
결과
참고
- https://recharts.org/en-US/api
- https://github.com/recharts/recharts/issues/1364#issuecomment-2608588147
반응형