Dear ImGui生态系统与社区资源

Dear ImGui生态系统与社区资源

【免费下载链接】imgui Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies 【免费下载链接】imgui 项目地址: https://gitcode.com/GitHub_Trending/im/imgui

Dear ImGui 的核心设计理念是保持轻量级和最小依赖,但正是这种简洁性催生了一个极其丰富的第三方生态系统。社区开发者围绕 ImGui 构建了大量扩展库和工具集,极大地扩展了其功能边界,使其能够胜任从简单的调试工具到复杂的专业应用程序的各种场景。

第三方扩展库与工具集介绍

Dear ImGui 的核心设计理念是保持轻量级和最小依赖,但正是这种简洁性催生了一个极其丰富的第三方生态系统。社区开发者围绕 ImGui 构建了大量扩展库和工具集,极大地扩展了其功能边界,使其能够胜任从简单的调试工具到复杂的专业应用程序的各种场景。

可视化与图表扩展

ImPlot - 高级2D绘图库

ImPlot 是 Dear ImGui 生态系统中最受欢迎的扩展之一,提供了专业的2D绘图功能。它支持多种图表类型,包括线图、散点图、柱状图、直方图、热力图等。

// ImPlot 基本使用示例
#include "implot.h"

void PlotDemo() {
    if (ImPlot::BeginPlot("My Plot")) {
        static double xs[100], ys[100];
        for (int i = 0; i < 100; ++i) {
            xs[i] = i * 0.1;
            ys[i] = sin(xs[i]);
        }
        ImPlot::PlotLine("sin(x)", xs, ys, 100);
        ImPlot::EndPlot();
    }
}

ImPlot 的主要特性包括:

  • 多种坐标轴类型(线性、对数、时间)
  • 实时数据可视化支持
  • 自定义样式和颜色主题
  • 交互式图表操作(缩放、平移、选择)
ImPlot3D - 3D绘图扩展

对于需要三维可视化的应用,ImPlot3D 提供了完整的3D绘图解决方案:

mermaid

编辑器与界面构建工具

节点编辑器生态系统

节点编辑器是图形化编程和可视化脚本的重要工具,ImGui 社区提供了多个高质量的节点编辑器实现:

编辑器名称主要特性适用场景
imgui-node-editor完整的节点图编辑,支持分组、注释游戏AI、材质编辑器
ImNodes轻量级节点图实现,易于集成简单的流程图、状态机
ImNodeFlow蓝图风格的可视化编程游戏逻辑、Shader编辑
// 节点编辑器基本结构示例
struct Node {
    ImVec2 Position;
    std::vector<Pin> Inputs;
    std::vector<Pin> Outputs;
};

void RenderNodeEditor() {
    ed::Begin("My Node Editor");
    for (auto& node : nodes) {
        ed::BeginNode(node.Id);
        ImGui::Text("Node Content");
        // 渲染输入输出引脚
        ed::EndNode();
    }
    // 渲染连接线
    ed::End();
}
文本与代码编辑器

对于需要代码编辑功能的应用程序,社区提供了多个文本编辑器扩展:

  • ImGuiColorTextEdit:支持语法高亮的彩色文本编辑器
  • Zep:可嵌入的编辑器,支持Vim键位绑定
  • Ned:基于GL着色器的高性能文本编辑器

专业工具与组件库

ImGuizmo - 3D变换控件

ImGuizmo 提供了专业的3D变换控件(移动、旋转、缩放),是3D编辑器和建模工具的必备组件:

// ImGuizmo 使用示例
#include "ImGuizmo.h"

void TransformGizmo(Camera& camera, Transform& transform) {
    ImGuizmo::SetOrthographic(false);
    ImGuizmo::BeginFrame();
    
    float view[16], projection[16];
    camera.GetViewMatrix(view);
    camera.GetProjectionMatrix(projection);
    
    float matrix[16];
    transform.ToMatrix(matrix);
    
    ImGuizmo::Manipulate(view, projection, 
        ImGuizmo::OPERATION::TRANSLATE, 
        ImGuizmo::MODE::LOCAL, matrix);
    
    if (ImGuizmo::IsUsing()) {
        transform.FromMatrix(matrix);
    }
}
文件对话框与资源管理

原生 ImGui 不包含文件对话框,但社区提供了多个解决方案:

文件对话框库特性平台支持
ImFileDialogWindows图标支持,图像预览Windows, Linux, macOS
ImGuiFileDialog缩略图,高级文件样式跨平台
ImGuiFD无额外依赖,轻量级所有平台

自动化与测试工具

ImGui Test Engine

对于需要自动化测试的应用程序,ImGui Test Engine 提供了完整的测试框架:

mermaid

样式与主题系统

社区提供了多种样式主题和UI美化工具:

// 主题应用示例
void ApplyDarkTheme() {
    ImGuiStyle& style = ImGui::GetStyle();
    ImVec4* colors = style.Colors;
    
    colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
    colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
    colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
    // ... 更多颜色设置
}

void ApplyCorporateTheme() {
    // 企业级主题配置
    ImGui::SpectrumStyle();
}

跨平台与远程访问

NetImgui - 远程UI渲染

NetImgui 允许将 ImGui 界面渲染到远程设备,非常适合嵌入式系统和远程调试:

远程方案传输协议适用场景
NetImguiTCP/IP游戏主机远程调试
imgui-wsWebSocket浏览器端显示
RemoteImGui自定义协议低延迟应用

语言绑定与框架集成

虽然 ImGui 本身是 C++ 库,但社区提供了几乎所有主流编程语言的绑定:

语言绑定成熟度特性
imgui-rs (Rust)⭐⭐⭐⭐⭐原生Rust接口,内存安全
DearPyGui (Python)⭐⭐⭐⭐⭐高性能,完整功能
ImGui.NET (C#)⭐⭐⭐⭐.NET生态集成
imgui-java (Java)⭐⭐⭐JNI绑定,Android支持

专业领域扩展

科学计算与数据分析

对于科学计算应用,社区提供了专门的扩展:

  • ImPlot:科学图表绘制
  • ImGui-Addons:数据表格和列表视图
  • ImSearch:即时搜索功能
游戏开发工具

游戏开发领域的专用扩展:

// 游戏开发工具集成示例
void GameDevTools() {
    // 性能分析器
    ImGui::ShowMetricsWindow();
    
    // 内存编辑器
    static MemoryEditor mem_edit;
    mem_edit.DrawWindow("Memory Editor", memory_buffer, buffer_size);
    
    // 实体检视器
    InspectEntity(selected_entity);
}

扩展生态系统的价值

Dear ImGui 的第三方扩展生态系统体现了开源社区的力量。这些扩展不仅填补了核心库的功能空白,还推动了整个生态系统的发展。开发者可以根据具体需求选择合适的扩展,快速构建专业的应用程序界面。

扩展库的丰富性也反映了 ImGui 架构的灵活性 - 其简洁的API设计使得第三方扩展能够无缝集成,同时保持高性能和低开销。这种设计哲学使得 ImGui 能够从小型工具扩展到大型专业应用程序,满足不同规模和复杂度的项目需求。

对于新用户来说,建议从核心功能开始,逐步根据项目需求引入相应的扩展库。社区维护的 Useful Extensions 页面是探索可用扩展的最佳起点。

ImPlot数据可视化库深度集成

ImPlot作为Dear ImGui生态系统中最成熟、功能最丰富的数据可视化扩展库,为实时数据监控、科学计算可视化和交互式数据分析提供了强大的工具集。作为GPU加速的即时模式绘图库,ImPlot完美继承了Dear ImGui的设计哲学,为开发者提供了无状态管理、高性能渲染和直观API的绘图解决方案。

核心特性与技术架构

ImPlot采用与Dear ImGui相同的即时模式架构,但其内部实现针对大规模数据可视化进行了深度优化。库的核心架构基于分层设计:

mermaid

多维度绘图类型支持

ImPlot提供了丰富的绘图类型,满足不同场景的数据可视化需求:

绘图类型适用场景性能特点交互功能
线图(Line Plots)时间序列数据、信号处理支持数十万点流畅渲染缩放、平移、数据点悬停
散点图(Scatter Plots)相关性分析、聚类数据多种标记类型和大小选择框选、图例交互
柱状图(Bars)分类数据比较垂直/水平/堆叠布局点击交互、动态更新
热力图(Heatmaps)矩阵数据、密度分布GPU加速渲染颜色映射调整、数值查看
直方图(Histograms)数据分布分析1D/2D分布可视化区间调整、统计信息

高级功能与集成模式

多轴系统与子图布局

ImPlot支持复杂的多轴配置,允许在同一绘图区域内创建多个x轴和y轴,为多维数据比较提供强大支持:

// 多轴配置示例
if (ImPlot::BeginPlot("Multi-Axis Plot", ImVec2(-1, 300))) {
    // 主Y轴
    ImPlot::SetupAxis(ImAxis_Y1, "Primary Y");
    ImPlot::PlotLine("Data Series 1", x_data, y1_data, point_count);
    
    // 次要Y轴
    ImPlot::SetupAxis(ImAxis_Y2, "Secondary Y", ImPlotAxisFlags_AuxDefault);
    ImPlot::SetAxes(ImAxis_X1, ImAxis_Y2);
    ImPlot::PlotLine("Data Series 2", x_data, y2_data, point_count);
    
    // 第三个Y轴
    ImPlot::SetupAxis(ImAxis_Y3, "Tertiary Y", ImPlotAxisFlags_AuxDefault);
    ImPlot::SetAxes(ImAxis_X1, ImAxis_Y3);
    ImPlot::PlotBars("Data Series 3", x_data, y3_data, point_count);
    
    ImPlot::EndPlot();
}
时间序列与对数坐标

针对科学计算和工程应用,ImPlot内置了专业级坐标系统:

// 时间序列和对数坐标配置
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxisScale(ImAxis_Y1, ImPlotScale_Log10);
ImPlot::SetupAxisFormat(ImAxis_X1, "%.1f s");
ImPlot::SetupAxisFormat(ImAxis_Y1, "%.2e");

性能优化策略

ImPlot在性能优化方面采用了多重策略,确保大规模数据集的流畅可视化:

数据分块与流式处理

mermaid

内存管理优化

ImPlot采用智能内存管理策略,减少不必要的内存分配和拷贝:

  • 数据引用而非拷贝:支持数据stride和getter回调
  • 顶点缓存复用:重用GPU顶点缓冲区
  • 动态资源分配:按需分配渲染资源

样式系统与主题定制

ImPlot提供了高度可定制的样式系统,支持多种主题配置:

// 样式配置示例
ImPlotStyle& style = ImPlot::GetStyle();
style.LineWeight = 2.0f;
style.MarkerSize = 6.0f;
style.PlotPadding = ImVec2(10, 10);
style.LabelPadding = ImVec2(5, 5);
style.LegendPadding = ImVec2(10, 10);

// 颜色映射配置
ImPlot::ColormapButton("Viridis", ImVec2(100, 0));
ImPlot::PushColormap(ImPlotColormap_Viridis);

实际应用案例

实时数据监控仪表盘
void RealTimeMonitoringDashboard() {
    static CircularBuffer<float> time_data(1000);
    static CircularBuffer<float> value_data(1000);
    
    // 更新实时数据
    time_data.push_back(ImGui::GetTime());
    value_data.push_back(GetSensorValue());
    
    if (ImPlot::BeginPlot("Real-Time Monitor", ImVec2(-1, 300))) {
        ImPlot::SetupAxes("Time", "Value", 
                         ImPlotAxisFlags_AutoFit | ImPlotAxisFlags_RangeFit);
        ImPlot::SetupAxisLimits(ImAxis_X1, 
                               ImGui::GetTime() - 10.0, 
                               ImGui::GetTime(), 
                               ImGuiCond_Always);
        ImPlot::PlotLine("Sensor Data", 
                        time_data.data(), 
                        value_data.data(), 
                        time_data.size());
        ImPlot::EndPlot();
    }
}
科学数据分析工具
void ScientificDataAnalyzer() {
    if (ImPlot::BeginPlot("Data Analysis", ImVec2(-1, 400), 
                         ImPlotFlags_Crosshairs)) {
        // 主数据系列
        ImPlot::PlotScatter("Experimental Data", x_data, y_data, count);
        
        // 拟合曲线
        ImPlot::SetNextLineStyle(IMPLOT_AUTO_COL, 2.0f);
        ImPlot::PlotLine("Fit Curve", x_fit, y_fit, fit_count);
        
        // 误差范围
        ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
        ImPlot::PlotShaded("Uncertainty", 
                          x_data, y_lower, y_upper, count);
        ImPlot::PopStyleVar();
        
        ImPlot::EndPlot();
    }
}

最佳实践与性能调优

为了获得最佳的ImPlot使用体验,建议遵循以下最佳实践:

  1. 数据预处理:对超大规模数据集进行适当的降采样
  2. 渲染批次优化:合并相同样式的绘图命令
  3. 内存管理:重用数据缓冲区,避免频繁分配
  4. 交互响应:合理设置刷新频率,平衡精度和性能

ImPlot与Dear ImGui的深度集成使得开发者能够在保持ImGui简洁API风格的同时,获得专业级的数据可视化能力。其模块化设计和扩展性保证了可以轻松适应各种复杂的应用场景,从简单的实时监控到复杂的科学计算可视化,ImPlot都能提供出色的解决方案。

社区最佳实践与常见问题解决方案

Dear ImGui作为一个轻量级、高效的即时模式GUI库,在游戏开发、工具制作和实时应用领域得到了广泛应用。通过社区多年的实践积累,形成了一系列最佳实践和常见问题的解决方案,这些经验对于新用户快速上手和避免常见陷阱至关重要。

ID管理最佳实践

ID冲突是Dear ImGui新手最常见的问题之一。每个交互式小部件都需要唯一的标识符,系统通过哈希标签字符串和ID栈来生成这些标识符。

// ❌ 错误示例:重复标签导致ID冲突
ImGui::Begin("MyWindow");
ImGui::Button("OK");
ImGui::Button("OK");      // 冲突!两个按钮有相同ID
ImGui::End();

// ✅ 正确示例1:使用唯一后缀
ImGui::Begin("MyWindow");
ImGui::Button("OK##1");
ImGui::Button("OK##2");
ImGui::End();

// ✅ 正确示例2:使用PushID/PopID
ImGui::Begin("MyWindow");
for (int i = 0; i < 3; i++) {
    ImGui::PushID(i);
    ImGui::Button("OK");
    ImGui::PopID();
}
ImGui::End();

ID栈的工作机制可以通过以下流程图理解:

mermaid

性能优化策略

Dear ImGui设计时就注重性能,但不当的使用方式仍可能导致性能问题。

避免频繁的状态变更:

// ❌ 低效:每帧都设置相同样式
void RenderUI() {
    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1,0,0,1));
    ImGui::Button("Click");
    ImGui::PopStyleColor();
}

// ✅ 高效:在初始化时设置一次
void InitUI() {
    ImGuiStyle& style = ImGui::GetStyle();
    style.Colors[ImGuiCol_Button] = ImVec4(1,0,0,1);
}

void RenderUI() {
    ImGui::Button("Click"); // 使用预定义样式
}

合理使用缓存机制:

// 使用静态变量缓存计算结果
void ExpensiveCalculationUI() {
    static float cached_result = 0.0f;
    static int frame_count = 0;
    
    if (frame_count++ % 60 == 0) { // 每60帧更新一次
        cached_result = CalculateExpensiveOperation();
    }
    
    ImGui::Text("Result: %.3f", cached_result);
}

内存管理最佳实践

Dear ImGui本身不进行动态内存分配(除了字体图集),但用户代码需要注意内存使用。

内存使用场景推荐做法避免做法
字符串处理使用静态缓冲区或预分配内存每帧分配新字符串
数据存储在应用层管理数据生命周期依赖ImGui存储大量数据
纹理资源复用纹理对象每帧创建新纹理
// 高效字符串处理示例
void RenderDynamicText() {
    static char buffer[256] = "";
    
    // 只在需要时更新缓冲区
    if (needs_update) {
        snprintf(buffer, sizeof(buffer), "Value: %d", current_value);
        needs_update = false;
    }
    
    ImGui::Text("%s", buffer);
}

输入处理与事件分发

正确处理输入事件是集成Dear ImGui的关键环节。

void HandleInputEvents() {
    ImGuiIO& io = ImGui::GetIO();
    
    // 1. 始终将输入传递给ImGui
    io.AddMousePosEvent(mouse_x, mouse_y);
    io.AddMouseButtonEvent(0, left_button_down);
    
    // 2. 根据WantCapture标志决定是否传递给应用
    if (!io.WantCaptureMouse) {
        // 处理应用特定的鼠标逻辑
        HandleGameMouseInput(mouse_x, mouse_y, left_button_down);
    }
    
    if (!io.WantCaptureKeyboard) {
        // 处理应用特定的键盘逻辑
        HandleGameKeyboardInput(key_pressed);
    }
}

输入事件处理流程:

mermaid

多字体与本地化支持

处理多语言和特殊字符时,字体配置至关重要。

void SetupFonts() {
    ImGuiIO& io = ImGui::GetIO();
    
    // 加载默认字体
    io.Fonts->AddFontDefault();
    
    // 加载中文字体支持
    ImFontConfig config;
    config.MergeMode = true;
    config.GlyphMinAdvanceX = 13.0f; // 如果希望合并的字体比主字体大,使用这个
    static const ImWchar icon_ranges[] = { 0x0020, 0x00FF, 0 };
    io.Fonts->AddFontFromFileTTF("chinese_font.ttf", 16.0f, &config, icon_ranges);
    
    // 构建字体图集
    io.Fonts->Build();
}

常见问题诊断工具

Dear ImGui提供了强大的调试工具来诊断问题:

void ShowDebugTools() {
    if (ImGui::Begin("Debug Tools")) {
        if (ImGui::Button("Show Metrics"))
            show_metrics = !show_metrics;
        if (ImGui::Button("Show ID Stack Tool"))
            show_id_stack = !show_metrics;
        if (ImGui::Button("Show Style Editor"))
            show_style_editor = !show_style_editor;
    }
    ImGui::End();
    
    if (show_metrics) ImGui::ShowMetricsWindow(&show_metrics);
    if (show_id_stack) ImGui::ShowIDStackToolWindow(&show_id_stack);
    if (show_style_editor) ImGui::ShowStyleEditor();
}

跨平台兼容性考虑

不同平台的集成需要注意特定问题:

Windows DPI处理:

void HandleDPI() {
    ImGuiIO& io = ImGui::GetIO();
    
    // 检测DPI变化并重新缩放
    if (dpi_scale_changed) {
        ImGuiStyle& style = ImGui::GetStyle();
        style.ScaleAllSizes(new_dpi_scale / current_dpi_scale);
        io.FontGlobalScale = new_dpi_scale;
        current_dpi_scale = new_dpi_scale;
    }
}

移动设备适配:

void SetupForTouchDevices() {
    ImGuiStyle& style = ImGui::GetStyle();
    
    // 增加触摸填充以提高触摸精度
    style.TouchPadding = ImVec2(8.0f, 8.0f);
    
    // 调整控件大小以适应触摸操作
    style.FramePadding = ImVec2(12.0f, 6.0f);
    style.ItemSpacing = ImVec2(10.0f, 7.0f);
}

通过遵循这些社区验证的最佳实践和解决方案,开发者可以避免常见的陷阱,构建出高性能、稳定的Dear ImGui应用程序。记住,当遇到问题时,查看Demo代码、使用内置的调试工具以及参考社区讨论往往是解决问题的最快途径。

项目贡献指南与未来发展路线

Dear ImGui作为一个开源项目,其成功离不开活跃的社区贡献和清晰的未来发展路线。了解如何参与贡献以及项目的未来规划,对于希望深入参与项目的开发者至关重要。

贡献流程与规范

提交Issue的准则

当您发现Bug或有功能建议时,首先需要了解正确的Issue提交流程:

mermaid

关键提交要求:

  • 版本信息:必须包含Dear ImGui版本号、分支名称
  • 环境详情:平台/渲染后端(imgui_impl_XXX文件)、操作系统
  • 代码示例:提供最小化、完整、可验证的示例(MCVE)
  • 可视化证据:附加截图或GIF/视频说明问题
  • 调试信息:如遇崩溃,提供调试器调用栈
Pull Request提交规范

提交PR时需遵循以下最佳实践:

// 代码风格示例
void ExampleFunction()
{
    // 使用4空格缩进(非制表符)
    int local_variable = 0;
    
    // 函数名使用PascalCase
    CalculateWidgetSize();
    
    // 成员变量使用CamelCase
    mMemberVariable = value;
    
    // 注释格式:文本注释和代码注释
    // 这是一个文本注释
    Calculate(); // 代码注释
}

PR提交清单:

  • ✅ 创建专用分支进行PR提交
  • ✅ 遵循现有代码风格规范
  • ✅ 提供使用场景描述和需求说明
  • ✅ 附加截图展示功能效果
  • ✅ 确保不破坏现有功能

未来发展路线与重点方向

核心架构演进

基于项目的TODO列表和开发规划,未来重点发展方向包括:

mermaid

技术债务与重构计划

项目当前的技术债务主要集中在以下几个方面:

优先级模块问题描述解决方案
颜色系统颜色转换辅助函数混乱重构为ImColorConvertXX统一API
字体系统TTF命名不符合实际支持格式移除"TTF"后缀,支持OTF
输入文本多行编辑功能不完善增强水平滚动、行号显示
导航系统扁平化导航存在问题修复页面导航和焦点恢复
社区驱动的功能开发

Dear ImGui采用社区驱动的开发模式,重要功能通常通过以下流程实现:

  1. 需求讨论:在GitHub Issues中讨论功能需求和实现方案
  2. 原型验证:贡献者提交PR展示可行性解决方案
  3. 代码审查:维护者进行详细代码审查和架构评估
  4. 合并维护:功能合并后由维护团队负责长期维护

参与贡献的多种方式

技术贡献途径

除了代码贡献外,社区成员还可以通过以下方式参与:

贡献类型具体形式价值评估
代码贡献Bug修复、功能开发高价值,需要技术深度
文档完善示例代码、使用指南中等价值,帮助新用户
问题排查Issue确认、复现验证基础价值,节省维护时间
资金支持商业赞助、个人捐赠关键支持,确保项目可持续
企业级支持模式

对于商业用户,项目提供专业的技术支持渠道:

  • 技术咨询:针对企业特定需求的深度技术支持
  • 定制开发:基于Dear ImGui的企业级定制解决方案
  • 培训服务:团队技术培训和最佳实践指导
  • 长期维护:确保关键业务应用的稳定性

开发实践与质量保证

代码质量标准

所有贡献都需要满足项目的质量标准:

// 质量检查示例
IM_ASSERT(condition && "详细的断言信息"); // 必须启用断言

// 内存安全
void* buffer = IM_ALLOC(size); // 使用项目内存分配器
IM_FREE(buffer);

// 平台兼容性
#if defined(_WIN32)
// Windows特定实现
#elif defined(__APPLE__)
// macOS特定实现
#endif
测试与验证要求

提交的功能需要经过充分测试:

  • 单元测试:核心功能的自动化测试覆盖
  • 回归测试:确保不破坏现有功能
  • 跨平台测试:在多个平台和渲染后端验证
  • 性能测试:评估性能影响和内存使用

通过遵循这些贡献指南和了解未来发展路线,开发者可以更有效地参与Dear ImGui项目,共同推动这个优秀GUI库的持续发展。

总结

Dear ImGui作为一个开源项目,其成功离不开活跃的社区贡献和清晰的未来发展路线。通过遵循贡献指南和了解未来发展路线,开发者可以更有效地参与Dear ImGui项目,共同推动这个优秀GUI库的持续发展。项目采用社区驱动的开发模式,重要功能通过需求讨论、原型验证、代码审查和合并维护的流程实现,确保了项目的健康发展和技术创新。

【免费下载链接】imgui Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies 【免费下载链接】imgui 项目地址: https://gitcode.com/GitHub_Trending/im/imgui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值