Chapter 28 · 基础图元

胶囊形

胶囊形(Capsule)是两端为半圆的"药丸"形状,常用于按钮、进度条轨道、血条等 UI 元素。

28

概念

  • 胶囊形:矩形 + 两端半圆。半圆半径 = 矩形短边 / 2,自动计算。
  • 方向自适应:宽 > 高 → 水平胶囊;高 > 宽 → 垂直胶囊;宽 = 高 → 圆形。
  • 用 xge_rect_t 定义:传入包围盒矩形,引擎自动计算圆角。

API 速查

函数说明
void xgeShapeCapsuleFill(xge_rect_t tRect, uint32_t iColor)填充胶囊形
void xgeShapeCapsuleFillPx(xge_rect_t tRect, uint32_t iColor)填充胶囊形(像素坐标)
void xgeShapeCapsuleStroke(xge_rect_t tRect, float fWidth, uint32_t iColor)描边胶囊形
void xgeShapeCapsuleStrokePx(xge_rect_t tRect, float fWidth, uint32_t iColor)描边胶囊形(像素坐标)

编译本章示例

gcc -O2 -I. -o ch28.exe ch28_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch28.exe

示例 1:水平胶囊按钮

// 水平胶囊(宽 200,高 50)
xge_rect_t btn = { 300, 275, 200, 50 };
xgeShapeCapsuleFill(btn, 0x4FD8C2FF);

// 描边胶囊
xge_rect_t outline = { 300, 350, 200, 50 };
xgeShapeCapsuleStroke(outline, 2.0f, 0xFFB454FF);

示例 2:进度条

float fProgress = 0.65f;  // 65%
float barX = 100, barY = 500, barW = 600, barH = 24;

// 背景轨道
xge_rect_t track = { barX, barY, barW, barH };
xgeShapeCapsuleFill(track, 0x333333FF);

// 前景进度
xge_rect_t fill = { barX, barY, barW * fProgress, barH };
xgeShapeCapsuleFill(fill, 0x4FD8C2FF);

示例 3:垂直胶囊 + 圆形

// 垂直胶囊
xge_rect_t vert = { 150, 100, 40, 160 };
xgeShapeCapsuleFill(vert, 0xFF6B5EFF);

// 正方形 → 圆形
xge_rect_t circle = { 250, 100, 80, 80 };
xgeShapeCapsuleFill(circle, 0x6DB3F2FF);

完整代码

将以下代码保存为 ch28_main.c,编译后运行即可看到胶囊形按钮与进度条效果:

#include "xge.h"

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    // 水平胶囊按钮(填充)
    xge_rect_t btn = { 300, 100, 200, 50 };
    xgeShapeCapsuleFill(btn, 0x4FD8C2FF);

    // 描边胶囊
    xge_rect_t outline = { 300, 180, 200, 50 };
    xgeShapeCapsuleStroke(outline, 2.0f, 0xFFB454FF);

    // 进度条:背景轨道 + 前景
    float fProgress = 0.65f;
    xge_rect_t track = { 100, 300, 600, 24 };
    xgeShapeCapsuleFill(track, 0x333333FF);
    xge_rect_t fill = { 100, 300, 600 * fProgress, 24 };
    xgeShapeCapsuleFill(fill, 0x4FD8C2FF);

    // 垂直胶囊
    xge_rect_t vert = { 150, 380, 40, 160 };
    xgeShapeCapsuleFill(vert, 0xFF6B5EFF);

    // 正方形 → 圆形
    xge_rect_t circle = { 250, 380, 80, 80 };
    xgeShapeCapsuleFill(circle, 0x6DB3F2FF);

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch28 - Capsule";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • 胶囊按钮:用 xge_rect_t 定义包围盒,xgeShapeCapsuleFill 自动取 min(W,H)/2 为圆角半径。
  • 进度条:先绘制灰色轨道(满宽),再绘制前景(宽度 × 进度比例),两层叠加形成进度效果。
  • 垂直胶囊:高 > 宽时自动变为垂直方向胶囊。
  • 正方形退化:宽 = 高时胶囊退化为正圆。

要点与陷阱

  • 半径自动:不需要手动指定圆角半径,引擎取 min(W,H)/2。
  • 进度条截断:当进度很小时,前景宽度 < 高度,形状退化为圆形。
  • 描边沿外轮廓:Stroke 沿胶囊外边缘绘制,线宽向内外各扩展一半。
  • 与圆角矩形区别:胶囊的圆角半径固定为短边一半;圆角矩形可自定义半径(第 29 章)。

进阶练习

  1. 实现一个带动画的胶囊进度条:进度从 0 平滑增长到 100%。
  2. 用胶囊形 + 圆形组合绘制一个温度计。
  3. 实现 Toggle 开关效果:胶囊轨道 + 圆形滑块左右移动。
胶囊形效果
图:胶囊形渲染效果