Skip to main content

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: strokeWidth hiệ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–200pxTăng thêm 20–30px (ví dụ: 220–240px hoặc 80% màn hình)
Chiều cao vùng gauge (height)~90–100pxTăng tương ứng (ví dụ: 110–130px)
Độ dày đường cong (strokeWidth)~6–8px16–18px (tham chiếu ảnh thiết kế chuẩn 6thang7)
Bán kính vòng cung (radius)~80–90pxTăng tương ứng chiều rộng mới
Đầu đường cong (strokeLinecap)square hoặc mặc địnhround (đầ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.000Hiển thị tốt ở 26–28px
Số triệu4.996.000Cần 24–26px để vừa
Số chục triệu70.000.000Cầ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 đổiGiá trị cũGiá trị mớiLý do
Chiều rộng gauge~190px~230pxTận dụng không gian màn hình
Bán kính~80px~95pxTỷ lệ theo chiều rộng mới
strokeWidth~7px17pxĐường cung nổi bật, dày
strokeLinecapsquareroundĐầu tròn mềm mại hơn
Font size số điểm~28–30px24px cố định (hoặc động)Tránh tràn khi số hàng chục triệu
letterSpacingmặc định-0.5Giúp số dài vừa trong gauge

Checklist Kỹ Thuật

  • Tăng GAUGE_WIDTH lên ~230px và GAUGE_RADIUS lên ~95px trong file PointScreen.tsx hoặc component gauge riêng.
  • Tăng STROKE_WIDTH lên 17 và đặt strokeLinecap="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ố định 24px.
  • Thêm letterSpacing: -0.5 cho 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.