JFreeChart之堆叠柱形图(StackedBar)

JFreeChart之堆叠柱形图(StackedBar)

最近的项目使用有个功能需要使用到堆叠柱形图,看了项目以前的代码实现没有想要的结果。所以自己就先到官网下载了 DemoDemo里有个打包好的Jar包,直接运行看到效果,但是坑爹的是貌似没有对应的源码,所以只能根据class名称直接google了,所幸在github里找到对应的源码。
点我下载 访问密码 f62b
这是运行Demo找到想要实现的效果的大致图:
enter description here
我最终想要实现的效果是这样的:
enter description here
如果想要实现这个效果,可以使用

  1. 1extendedstackedbarrenderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator("{3}"
  2. 2 NumberFormat.getPercentInstance(), new DecimalFormat("#0.0%"))); 
  3. 3 

但是柱体的返回的值是10.1/50.1=20.2%,40.1/50.1=79.8%
enter description here
这不符合预期目标,所以就去看了一下源码,在StandardCategoryItemLabelGenerator的父类AbstractCategoryItemLabelGenerator中发现有createItemArray这么一个方法:
enter description here
可以发现柱体的标签值应该是由这个方法进行返回的,因此自己就对StandardCategoryItemLabelGenerator进行了继承,并重写了这个方法。
ExtendedStandardCategoryItemLabelGeneratory中增加了isPercent作为标签值是显示百分比还是仅仅格式化的判断参数,并重写了createItemArray这个方法。
enter description here
此时得到的效果如图:
enter description here
然而,柱体的总值还是没有格式化。再看了一下ExtendedStackedBarRenderer这个类的代码,找到了totalFormat这个属性,将其值赋为new DecimalFormat("#0.0%")。测试:
enter description here
基本是想要的最终结果,下面是测试代码

  1. 1 <dependency> 
  2. 2 <groupId>jfree</groupId> 
  3. 3 <artifactId>jfreechart</artifactId> 
  4. 4 <version>1.0.13</version> 
  5. 5 </dependency> 

ExtendedStackedBarRenderer

  1. 1package com.springapp.jfreechar; 
  2. 2 
  3. 3import java.awt.Color; 
  4. 4import java.awt.Font; 
  5. 5import java.awt.Graphics2D; 
  6. 6import java.awt.geom.Rectangle2D; 
  7. 7import java.text.DecimalFormat; 
  8. 8import java.text.NumberFormat; 
  9. 9 
  10. 10import org.jfree.chart.axis.CategoryAxis; 
  11. 11import org.jfree.chart.axis.ValueAxis; 
  12. 12import org.jfree.chart.entity.CategoryItemEntity; 
  13. 13import org.jfree.chart.entity.EntityCollection; 
  14. 14import org.jfree.chart.labels.CategoryToolTipGenerator; 
  15. 15import org.jfree.chart.plot.CategoryPlot; 
  16. 16import org.jfree.chart.plot.PlotOrientation; 
  17. 17import org.jfree.chart.renderer.category.CategoryItemRendererState; 
  18. 18import org.jfree.chart.renderer.category.StackedBarRenderer; 
  19. 19import org.jfree.data.category.CategoryDataset; 
  20. 20import org.jfree.text.TextUtilities; 
  21. 21import org.jfree.ui.TextAnchor; 
  22. 22 
  23. 23public class ExtendedStackedBarRenderer extends StackedBarRenderer
  24. 24 
  25. 25 private static final long serialVersionUID = 1L
  26. 26 private boolean showPositiveTotal; 
  27. 27 private boolean showNegativeTotal; 
  28. 28 private Font totalLabelFont; 
  29. 29 private NumberFormat totalFormatter; 
  30. 30 public ExtendedStackedBarRenderer()
  31. 31 showPositiveTotal = true
  32. 32 showNegativeTotal = true
  33. 33 totalLabelFont = new Font("SansSerif", 1, 12); 
  34. 34 totalFormatter = new DecimalFormat("#0.0%"); 
  35. 35
  36. 36 
  37. 37 /** 
  38. 38 * StackedBarRenderer 没有这个构造方法的,传入一个NumberFormat类,可以自定义实现每个柱体值显示格式 
  39. 39 * @param totalFormatter 
  40. 40 */ 
  41. 41 public ExtendedStackedBarRenderer(NumberFormat totalFormatter)
  42. 42 showPositiveTotal = true
  43. 43 showNegativeTotal = true
  44. 44 totalLabelFont = new Font("SansSerif", 1, 12); 
  45. 45 this.totalFormatter = totalFormatter; 
  46. 46
  47. 47 
  48. 48 public NumberFormat getTotalFormatter()
  49. 49 return totalFormatter; 
  50. 50
  51. 51 
  52. 52 public void setTotalFormatter(NumberFormat numberformat)
  53. 53 if (numberformat == null) { 
  54. 54 throw new IllegalArgumentException("Null format not permitted."); 
  55. 55 } else
  56. 56 totalFormatter = numberformat; 
  57. 57 return
  58. 58
  59. 59
  60. 60 
  61. 61 public void drawItem(Graphics2D graphics2d, CategoryItemRendererState categoryitemrendererstate, Rectangle2D rectangle2d, CategoryPlot categoryplot, CategoryAxis categoryaxis, 
  62. 62 ValueAxis valueaxis, CategoryDataset categorydataset, int i, int j, int k)
  63. 63 Number number = categorydataset.getValue(i, j); 
  64. 64 if (number == null
  65. 65 return
  66. 66 double d = number.doubleValue(); 
  67. 67 PlotOrientation plotorientation = categoryplot.getOrientation(); 
  68. 68 double d1 = categoryaxis.getCategoryMiddle(j, getColumnCount(), rectangle2d, categoryplot.getDomainAxisEdge()) - categoryitemrendererstate.getBarWidth() / 2D; 
  69. 69 double d2 = 0.0D; 
  70. 70 double d3 = 0.0D; 
  71. 71 for (int l = 0; l < i; l++) { 
  72. 72 Number number1 = categorydataset.getValue(l, j); 
  73. 73 if (number1 == null
  74. 74 continue
  75. 75 double d5 = number1.doubleValue(); 
  76. 76 if (d5 > 0.0D) 
  77. 77 d2 += d5; 
  78. 78 else 
  79. 79 d3 += d5; 
  80. 80
  81. 81 
  82. 82 org.jfree.ui.RectangleEdge rectangleedge = categoryplot.getRangeAxisEdge(); 
  83. 83 double d4; 
  84. 84 double d6; 
  85. 85 if (d > 0.0D) { 
  86. 86 d4 = valueaxis.valueToJava2D(d2, rectangle2d, rectangleedge); 
  87. 87 d6 = valueaxis.valueToJava2D(d2 + d, rectangle2d, rectangleedge); 
  88. 88 } else
  89. 89 d4 = valueaxis.valueToJava2D(d3, rectangle2d, rectangleedge); 
  90. 90 d6 = valueaxis.valueToJava2D(d3 + d, rectangle2d, rectangleedge); 
  91. 91
  92. 92 double d7 = Math.min(d4, d6); 
  93. 93 double d8 = Math.max(Math.abs(d6 - d4), getMinimumBarLength()); 
  94. 94 Rectangle2D.Double double1 = null
  95. 95 if (plotorientation == PlotOrientation.HORIZONTAL) 
  96. 96 double1 = new Rectangle2D.Double(d7, d1, d8, categoryitemrendererstate.getBarWidth()); 
  97. 97 else 
  98. 98 double1 = new Rectangle2D.Double(d1, d7, categoryitemrendererstate.getBarWidth(), d8); 
  99. 99 java.awt.Paint paint = getItemPaint(i, j); 
  100. 100 graphics2d.setPaint(paint); 
  101. 101 graphics2d.fill(double1); 
  102. 102 if (isDrawBarOutline() && categoryitemrendererstate.getBarWidth() > 3D) { 
  103. 103 graphics2d.setStroke(getItemStroke(i, j)); 
  104. 104 graphics2d.setPaint(getItemOutlinePaint(i, j)); 
  105. 105 graphics2d.draw(double1); 
  106. 106
  107. 107 org.jfree.chart.labels.CategoryItemLabelGenerator categoryitemlabelgenerator = getItemLabelGenerator(i, j); 
  108. 108 if (categoryitemlabelgenerator != null && isItemLabelVisible(i, j)) 
  109. 109 drawItemLabel(graphics2d, categorydataset, i, j, categoryplot, categoryitemlabelgenerator, double1, d < 0.0D); 
  110. 110 if (d > 0.0D) { 
  111. 111 if (showPositiveTotal && isLastPositiveItem(categorydataset, i, j)) { 
  112. 112 graphics2d.setPaint(Color.black); 
  113. 113 graphics2d.setFont(totalLabelFont); 
  114. 114 double d9 = calculateSumOfPositiveValuesForCategory(categorydataset, j); 
  115. 115 float f = (float) double1.getCenterX(); 
  116. 116 float f2 = (float) double1.getMinY() - 4F
  117. 117 TextAnchor textanchor = TextAnchor.BOTTOM_CENTER; 
  118. 118 if (plotorientation == PlotOrientation.HORIZONTAL) { 
  119. 119 f = (float) double1.getMaxX() + 4F
  120. 120 f2 = (float) double1.getCenterY(); 
  121. 121 textanchor = TextAnchor.CENTER_LEFT; 
  122. 122
  123. 123 TextUtilities.drawRotatedString(totalFormatter.format(d9), graphics2d, f, f2, textanchor, 0.0D, TextAnchor.CENTER); 
  124. 124
  125. 125 } else if (showNegativeTotal && isLastNegativeItem(categorydataset, i, j))
  126. 126 graphics2d.setPaint(Color.black); 
  127. 127 graphics2d.setFont(totalLabelFont); 
  128. 128 double d10 = calculateSumOfNegativeValuesForCategory(categorydataset, j); 
  129. 129 float f1 = (float) double1.getCenterX(); 
  130. 130 float f3 = (float) double1.getMaxY() + 4F
  131. 131 TextAnchor textanchor1 = TextAnchor.TOP_CENTER; 
  132. 132 if (plotorientation == PlotOrientation.HORIZONTAL) { 
  133. 133 f1 = (float) double1.getMinX() - 4F
  134. 134 f3 = (float) double1.getCenterY(); 
  135. 135 textanchor1 = TextAnchor.CENTER_RIGHT; 
  136. 136
  137. 137 TextUtilities.drawRotatedString(totalFormatter.format(d10), graphics2d, f1, f3, textanchor1, 0.0D, TextAnchor.CENTER); 
  138. 138
  139. 139 if (categoryitemrendererstate.getInfo() != null) { 
  140. 140 EntityCollection entitycollection = categoryitemrendererstate.getEntityCollection(); 
  141. 141 if (entitycollection != null) { 
  142. 142 String s = null
  143. 143 CategoryToolTipGenerator categorytooltipgenerator = getToolTipGenerator(i, j); 
  144. 144 if (categorytooltipgenerator != null
  145. 145 s = categorytooltipgenerator.generateToolTip(categorydataset, i, j); 
  146. 146 String s1 = null
  147. 147 if (getItemURLGenerator(i, j) != null
  148. 148 s1 = getItemURLGenerator(i, j).generateURL(categorydataset, i, j); 
  149. 149 CategoryItemEntity categoryitementity = new CategoryItemEntity(double1, s, s1, categorydataset, categorydataset.getRowKey(i), categorydataset.getColumnKey(j)); 
  150. 150 entitycollection.add(categoryitementity); 
  151. 151
  152. 152
  153. 153
  154. 154 
  155. 155 private boolean isLastPositiveItem(CategoryDataset categorydataset, int i, int j)
  156. 156 boolean flag = true
  157. 157 Number number = categorydataset.getValue(i, j); 
  158. 158 if (number == null
  159. 159 return false
  160. 160 for (int k = i + 1; k < categorydataset.getRowCount(); k++) { 
  161. 161 Number number1 = categorydataset.getValue(k, j); 
  162. 162 if (number1 != null
  163. 163 flag = flag && number1.doubleValue() <= 0.0D; 
  164. 164
  165. 165 
  166. 166 return flag; 
  167. 167
  168. 168 
  169. 169 private boolean isLastNegativeItem(CategoryDataset categorydataset, int i, int j)
  170. 170 boolean flag = true
  171. 171 Number number = categorydataset.getValue(i, j); 
  172. 172 if (number == null
  173. 173 return false
  174. 174 for (int k = i + 1; k < categorydataset.getRowCount(); k++) { 
  175. 175 Number number1 = categorydataset.getValue(k, j); 
  176. 176 if (number1 != null
  177. 177 flag = flag && number1.doubleValue() >= 0.0D; 
  178. 178
  179. 179 
  180. 180 return flag; 
  181. 181
  182. 182 
  183. 183 private double calculateSumOfPositiveValuesForCategory(CategoryDataset categorydataset, int i)
  184. 184 double d = 0.0D; 
  185. 185 for (int j = 0; j < categorydataset.getRowCount(); j++) { 
  186. 186 Number number = categorydataset.getValue(j, i); 
  187. 187 if (number == null
  188. 188 continue
  189. 189 double d1 = number.doubleValue(); 
  190. 190 if (d1 > 0.0D) 
  191. 191 d += d1; 
  192. 192
  193. 193 
  194. 194 return d; 
  195. 195
  196. 196 
  197. 197 private double calculateSumOfNegativeValuesForCategory(CategoryDataset categorydataset, int i)
  198. 198 double d = 0.0D; 
  199. 199 for (int j = 0; j < categorydataset.getRowCount(); j++) { 
  200. 200 Number number = categorydataset.getValue(j, i); 
  201. 201 if (number == null
  202. 202 continue
  203. 203 double d1 = number.doubleValue(); 
  204. 204 if (d1 < 0.0D) 
  205. 205 d += d1; 
  206. 206
  207. 207 
  208. 208 return d; 
  209. 209
  210. 210 
  211. 211
  212. 212 

ExtendedStandardCategoryItemLabelGeneratory

  1. 1package com.springapp.jfreechar; 
  2. 2 
  3. 3import org.jfree.chart.HashUtilities; 
  4. 4import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator; 
  5. 5import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; 
  6. 6import org.jfree.data.DataUtilities; 
  7. 7import org.jfree.data.category.CategoryDataset; 
  8. 8import org.jfree.util.ObjectUtilities; 
  9. 9import org.jfree.util.PublicCloneable; 
  10. 10 
  11. 11import java.io.Serializable; 
  12. 12import java.text.DateFormat; 
  13. 13import java.text.MessageFormat; 
  14. 14import java.text.NumberFormat; 
  15. 15 
  16. 16public class ExtendedStandardCategoryItemLabelGeneratory extends StandardCategoryItemLabelGenerator implements PublicCloneable, Cloneable, Serializable
  17. 17 
  18. 18 private static final long serialVersionUID = -7108591260223293197L
  19. 19 private String labelFormat; 
  20. 20 private String nullValueString; 
  21. 21 private NumberFormat numberFormat; 
  22. 22 private DateFormat dateFormat; 
  23. 23 private NumberFormat percentFormat; 
  24. 24 //新增加了参数,柱体series的值是否是总值的百分比,还是仅仅将原来的小数转化为百分数 
  25. 25 private boolean isPercent = false
  26. 26 
  27. 27 public ExtendedStandardCategoryItemLabelGeneratory(String labelFormat, NumberFormat formatter, NumberFormat percentFormatter,boolean isPercent)
  28. 28 super(labelFormat, formatter, percentFormatter); 
  29. 29 if(labelFormat == null) { 
  30. 30 throw new IllegalArgumentException("Null \'labelFormat\' argument."); 
  31. 31 } else if(formatter == null)
  32. 32 throw new IllegalArgumentException("Null \'formatter\' argument."); 
  33. 33 } else if(percentFormatter == null)
  34. 34 throw new IllegalArgumentException("Null \'percentFormatter\' argument."); 
  35. 35 } else
  36. 36 this.labelFormat = labelFormat; 
  37. 37 this.numberFormat = formatter; 
  38. 38 this.percentFormat = percentFormatter; 
  39. 39 this.dateFormat = null
  40. 40 this.nullValueString = "-"
  41. 41 if (isPercent) 
  42. 42 this.isPercent = isPercent; 
  43. 43
  44. 44 
  45. 45
  46. 46 
  47. 47 @Override 
  48. 48 protected String generateLabelString(CategoryDataset dataset, int row, int column)
  49. 49 if(dataset == null) { 
  50. 50 throw new IllegalArgumentException("Null \'dataset\' argument."); 
  51. 51 } else
  52. 52 String result = null
  53. 53 Object[] items = this.createItemArray(dataset, row, column); 
  54. 54 result = MessageFormat.format(this.labelFormat, items); 
  55. 55 return result; 
  56. 56
  57. 57
  58. 58 @Override 
  59. 59 protected Object[] createItemArray(CategoryDataset dataset, int row, int column) { 
  60. 60 Object[] result = new Object[]{dataset.getRowKey(row).toString(), dataset.getColumnKey(column).toString(), null, null}; 
  61. 61 Number value = dataset.getValue(row, column); 
  62. 62 if(value != null) { 
  63. 63 if(this.numberFormat != null) { 
  64. 64 result[2] = this.numberFormat.format(value); 
  65. 65 } else if(this.dateFormat != null)
  66. 66 result[2] = this.dateFormat.format(value); 
  67. 67
  68. 68 } else
  69. 69 result[2] = this.nullValueString; 
  70. 70
  71. 71 
  72. 72 if(value != null) { 
  73. 73 double total = DataUtilities.calculateColumnTotal(dataset, column); 
  74. 74 // 
  75. 75 double percent = 0D;// / total; 
  76. 76 if (this.isPercent) 
  77. 77 //StandardCategoryItemLabelGenerator 返回的值是百分比 
  78. 78 percent = value.doubleValue() / total; 
  79. 79 else 
  80. 80 //返回自己原来的值 
  81. 81 percent = value.doubleValue(); 
  82. 82 //格式化 
  83. 83 result[3] = this.percentFormat.format(percent); 
  84. 84
  85. 85 
  86. 86 return result; 
  87. 87
  88. 88 
  89. 89 
  90. 90
  91. 91 

StackedBarChartDemo3

  1. 1package com.springapp.jfreechar; 
  2. 2 
  3. 3import java.awt.*; 
  4. 4import java.text.DecimalFormat; 
  5. 5import java.text.NumberFormat; 
  6. 6import java.util.Iterator; 
  7. 7 
  8. 8import javax.swing.*; 
  9. 9 
  10. 10import com.sun.javafx.charts.Legend; 
  11. 11import org.jfree.chart.*; 
  12. 12import org.jfree.chart.axis.*; 
  13. 13import org.jfree.chart.labels.*; 
  14. 14import org.jfree.chart.plot.CategoryPlot; 
  15. 15import org.jfree.chart.plot.PlotOrientation; 
  16. 16import org.jfree.chart.title.LegendTitle; 
  17. 17import org.jfree.data.category.CategoryDataset; 
  18. 18import org.jfree.data.category.DefaultCategoryDataset; 
  19. 19import org.jfree.ui.ApplicationFrame; 
  20. 20import org.jfree.ui.RectangleEdge; 
  21. 21import org.jfree.ui.RefineryUtilities; 
  22. 22import org.jfree.ui.TextAnchor; 
  23. 23 
  24. 24// Referenced classes of package demo: 
  25. 25// ExtendedStackedBarRenderer 
  26. 26 
  27. 27public class StackedBarChartDemo3 extends ApplicationFrame
  28. 28 
  29. 29 private static final long serialVersionUID = 1L
  30. 30 
  31. 31 public StackedBarChartDemo3(String s)
  32. 32 super(s); 
  33. 33 JPanel jpanel = createDemoPanel(); 
  34. 34 jpanel.setPreferredSize(new Dimension(500, 270)); 
  35. 35 setContentPane(jpanel); 
  36. 36
  37. 37 
  38. 38 private static CategoryDataset createDataset()
  39. 39 DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset(); 
  40. 40 defaultcategorydataset.addValue(.101D, "Series 1", "Cross Contamination (4.3)"); 
  41. 41 defaultcategorydataset.addValue(.4D, "Series 2", "Cross Contamination (4.3)"); 
  42. 42 return defaultcategorydataset; 
  43. 43
  44. 44 
  45. 45 private static JFreeChart createChart(CategoryDataset categorydataset)
  46. 46 
  47. 47 JFreeChart jfreechart = ChartFactory.createStackedBarChart("Stacked Bar Chart Demo 3", "Category", "Value", categorydataset, PlotOrientation.VERTICAL, true, true, false); 
  48. 48 
  49. 49 CategoryPlot categoryplot = (CategoryPlot) jfreechart.getPlot(); 
  50. 50 //柱体 
  51. 51 ExtendedStackedBarRenderer extendedstackedbarrenderer = new ExtendedStackedBarRenderer(new DecimalFormat("#0.0%")); 
  52. 52 //柱体标签是否可见 
  53. 53 extendedstackedbarrenderer.setBaseItemLabelsVisible(true); 
  54. 54 Font labelFont = new Font("Arial", Font.PLAIN, 12); 
  55. 55 extendedstackedbarrenderer.setBaseItemLabelPaint(new GradientPaint(0.0f, 0.0f, new Color(255, 255, 255), 0.0f, 0.0f, new Color(0, 0, 0))); 
  56. 56 //设置柱体标签值的格式 
  57. 57 ExtendedStandardCategoryItemLabelGeneratory generator = new ExtendedStandardCategoryItemLabelGeneratory("{3}"
  58. 58 NumberFormat.getPercentInstance(), new DecimalFormat("#0.0%"),false); 
  59. 59 extendedstackedbarrenderer.setBaseItemLabelGenerator(generator); 
  60. 60 //自定义柱体颜色 
  61. 61 Paint p0 = new GradientPaint(0.0f, 0.0f, new Color(237, 125, 49), 0.0f, 0.0f, new Color(237, 125, 49)); 
  62. 62 extendedstackedbarrenderer.setSeriesPaint(0, p0); 
  63. 63 Paint p1 = new GradientPaint(0.0f, 0.0f, new Color(91, 155, 213), 0.0f, 0.0f, new Color(91, 155, 213)); 
  64. 64 extendedstackedbarrenderer.setSeriesPaint(1, p1); 
  65. 65 
  66. 66 categoryplot.setRenderer(extendedstackedbarrenderer); 
  67. 67 
  68. 68 //Y 轴 
  69. 69 NumberAxis numberaxis = (NumberAxis) categoryplot.getRangeAxis(); 
  70. 70 //不设置是自动显示步长 
  71. 71 numberaxis.setTickUnit(new NumberTickUnit(0.05)); 
  72. 72 numberaxis.setLowerMargin(0.14999999999999999D); 
  73. 73 numberaxis.setUpperMargin(0.14999999999999999D); 
  74. 74 //设置是否是百分率 
  75. 75 numberaxis.setNumberFormatOverride(NumberFormat.getPercentInstance()); 
  76. 76 
  77. 77 //X 辆 
  78. 78 CategoryAxis categoryAxis = categoryplot.getDomainAxis(); 
  79. 79 //x轴旋转 
  80. 80 categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)); 
  81. 81 
  82. 82 //标注 
  83. 83 LegendTitle legendtitle = (LegendTitle)jfreechart.getLegend(); 
  84. 84 legendtitle.setBorder(0, 0, 0, 0); 
  85. 85 return jfreechart; 
  86. 86
  87. 87 
  88. 88 public static JPanel createDemoPanel()
  89. 89 JFreeChart jfreechart = createChart(createDataset()); 
  90. 90 return new ChartPanel(jfreechart); 
  91. 91
  92. 92 
  93. 93 public static void main(String args[])
  94. 94 StackedBarChartDemo3 stackedbarchartdemo3 = new StackedBarChartDemo3("Stacked Bar Chart Demo 3"); 
  95. 95 stackedbarchartdemo3.pack(); 
  96. 96 RefineryUtilities.centerFrameOnScreen(stackedbarchartdemo3); 
  97. 97 stackedbarchartdemo3.setVisible(true); 
  98. 98
  99. 99
  100. 100 
  101. 101 

转载于:https://www.cnblogs.com/leongfeng/p/5259897.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值