Yêu Cầu Chỉnh Sửa: Tăng Kích Thước Vòng Cung Gauge & Giảm Font Số Điểm
Ngày cập nhật: 08/07/2026
Loại: UI/UX Gauge Chart Sizing & Typography Adjustment
Màn hình: Điểm (PointScreen) — Khu vực biểu đồ "Point xét hạng"
Ảnh feedback:
Tài liệu liên quan: Xem thêm đặc tả thiết kế gốc tại
docs/golden-membership/APP/6thang7/typography-and-gauge-design-spec.md
1. Vấn Đề Hiện Tại
Nhìn vào màn hình thực tế (ảnh trên), biểu đồ bán nguyệt (gauge) đang có các vấn đề:
1.1 Vòng cung quá nhỏ
- Bán kính vòng cung nhỏ: Gauge trông thu hẹp, chiều rộng và chiều cao của toàn bộ vòng cung chưa tận dụng không gian màn hình đang có.
- Đường cong mỏng:
strokeWidthhiện tại quá nhỏ, đường cung gần như chỉ là một đường kẻ mảnh — không tạo được điểm nhấn thị giác.
1.2 Font số điểm trong gauge quá lớn — sẽ bị tràn khi số lớn
- Hiện tại số "4.000" đang hiển thị vừa vặn, nhưng khi người dùng tích lũy lên hàng triệu hoặc chục triệu điểm (ví dụ:
70.000.000,4.996.000), số sẽ tràn ra ngoài vòng cung hoặc bị cắt. - Cần giảm font size xuống 1–2px để chuỗi số dài vẫn vừa trong không gian bên trong gauge.
2. Yêu Cầu Chỉnh Sửa
2.1 Tăng kích thước vòng cung Gauge
| Thông số | Hiện tại (ước tính) | Yêu cầu mới |
|---|---|---|
Chiều rộng gauge (width) | ~180–200px | Tăng thêm 20–30px (ví dụ: 220–240px hoặc 80% màn hình) |
Chiều cao vùng gauge (height) | ~90–100px | Tăng tương ứng (ví dụ: 110–130px) |
Độ dày đường cong (strokeWidth) | ~6–8px | 16–18px (tham chiếu ảnh thiết kế chuẩn 6thang7) |
Bán kính vòng cung (radius) | ~80–90px | Tăng tương ứng chiều rộng mới |
Đầu đường cong (strokeLinecap) | square hoặc mặc định | round (đầu tròn) |
2.2 Giảm font size số điểm bên trong Gauge
Số điểm hiển thị bên trong vòng cung cần nhỏ hơn để đủ chỗ cho số có nhiều chữ số:
| Trường hợp số | Ví dụ | Yêu cầu font size |
|---|---|---|
| Số nhỏ (hàng nghìn) | 4.000 | Hiển thị tốt ở 26–28px |
| Số triệu | 4.996.000 | Cần 24–26px để vừa |
| Số chục triệu | 70.000.000 | Cần 22–24px để vừa |
Giải pháp tốt nhất: Dùng font size động — tự thu nhỏ theo độ dài chuỗi số. Nếu không có thư viện hỗ trợ, dùng font size cố định
24px— đủ nhỏ cho số chục triệu, vẫn đủ to để đọc rõ.
// Tính font size động theo độ dài chuỗi số
const getGaugeFontSize = (value) => {
const formatted = value.toLocaleString('vi-VN'); // "70.000.000"
if (formatted.length <= 7) return 28; // <= 7 ký tự (hàng triệu): 28px
if (formatted.length <= 10) return 24; // 8-10 ký tự (chục triệu): 24px
return 20; // > 10 ký tự: 20px (dự phòng)
};
3. Gợi Ý Cấu Trúc Code (React Native + react-native-svg)
import Svg, { Path, G } from 'react-native-svg';
// ===== Hằng số kích thước Gauge =====
const GAUGE_WIDTH = 230; // Tăng chiều rộng tổng thể
const GAUGE_RADIUS = 95; // Bán kính (= GAUGE_WIDTH/2 - strokeWidth/2)
const STROKE_WIDTH = 17; // Dày hơn so với hiện tại
const STROKE_LINECAP = 'round';
const GAUGE_HEIGHT = GAUGE_RADIUS + STROKE_WIDTH + 10; // Chiều cao vùng SVG
// ===== Component Gauge =====
const MembershipGauge = ({ currentPoints, maxPoints, rank }) => {
const progress = Math.min(currentPoints / maxPoints, 1);
const fontSize = getGaugeFontSize(currentPoints);
// Tính toán arc path...
const cx = GAUGE_WIDTH / 2;
const cy = GAUGE_RADIUS + STROKE_WIDTH / 2;
return (
<View style={{ alignItems: 'center' }}>
<Svg width={GAUGE_WIDTH} height={GAUGE_HEIGHT}>
{/* Nền xám */}
<Path
d={buildArcPath(cx, cy, GAUGE_RADIUS, 0, 1)}
stroke="#E0E0E0"
strokeWidth={STROKE_WIDTH}
strokeLinecap={STROKE_LINECAP}
fill="none"
/>
{/* Thanh tiến trình teal */}
<Path
d={buildArcPath(cx, cy, GAUGE_RADIUS, 0, progress)}
stroke="#2BA89A"
strokeWidth={STROKE_WIDTH}
strokeLinecap={STROKE_LINECAP}
fill="none"
/>
</Svg>
{/* Số điểm — font size động */}
<Text style={[styles.gaugeValue, { fontSize }]}>
{currentPoints.toLocaleString('vi-VN')}
</Text>
{/* Hạng */}
<Text style={styles.rankLabel}>{rank}</Text>
</View>
);
};
const styles = StyleSheet.create({
gaugeValue: {
// fontSize được truyền động qua prop
fontWeight: '700',
color: '#1A1A1A',
textAlign: 'center',
letterSpacing: -0.5, // Thu nhẹ khoảng cách chữ để số dài vừa hơn
marginTop: -GAUGE_HEIGHT * 0.4, // Kéo số vào trong vùng gauge
},
rankLabel: {
fontSize: 14,
fontWeight: '600',
color: '#2BA89A',
textAlign: 'center',
marginTop: 4,
},
});
4. Bảng Tóm Tắt Thay Đổi
| Thay đổi | Giá trị cũ | Giá trị mới | Lý do |
|---|---|---|---|
| Chiều rộng gauge | ~190px | ~230px | Tận dụng không gian màn hình |
| Bán kính | ~80px | ~95px | Tỷ lệ theo chiều rộng mới |
strokeWidth | ~7px | 17px | Đường cung nổi bật, dày |
strokeLinecap | square | round | Đầu tròn mềm mại hơn |
| Font size số điểm | ~28–30px | 24px cố định (hoặc động) | Tránh tràn khi số hàng chục triệu |
letterSpacing | mặc định | -0.5 | Giúp số dài vừa trong gauge |
Checklist Kỹ Thuật
- Tăng
GAUGE_WIDTHlên ~230px vàGAUGE_RADIUSlên ~95px trong filePointScreen.tsxhoặc component gauge riêng. - Tăng
STROKE_WIDTHlên 17 và đặtstrokeLinecap="round"cho cả 2 path (nền + progress). - Giảm font size số điểm bên trong gauge: áp dụng hàm
getGaugeFontSize()tính động theo độ dài, hoặc đặt cố định24px. - Thêm
letterSpacing: -0.5cho Text số điểm để chuỗi số dài không bị quá rộng. - Điều chỉnh
marginTopâm của Text số điểm để tọa độ vẫn nằm bên trong vùng gauge sau khi tăng kích thước. - Test với các giá trị điểm:
4.000,4.996.000,70.000.000để xác nhận số không bị tràn trong mọi trường hợp. - Test trên màn hình nhỏ (iPhone SE 375px) và màn hình lớn (414px+) để gauge không bị cắt hai bên.