图形系统开发实战课程:基础篇——5.渲染效果


在这里插入图片描述

图形开发学院|GraphAnyWhere


第五章:渲染效果

\quad 在前几章的内容中,我们讲述了各种几何图形的绘制,并学习了使用颜色填充几何图形或者给几何图形描边,本章将会讲解在绘制几何图形的时候使用各种渲染效果。本章的内容包括:

  • 边框样式
  • 阴影效果
  • 渐变效果
  • 图案/纹理效果

1. 边框样式

在图形系统开发实战-基础篇:绘制基本图形中讲述了在绘制矩形、直线、多边形、圆等内容时我们学习到了以下几类边框样式:

  • 通过strokeStyle属性可以指定边框的颜色
  • 通过lineWidth属性可以指定描边的粗细
  • 通过setLineDash()方法可以指定虚线风格

本节我们还将学习:

  • 线条末端样式
  • 线条连接风格
  • 斜接面限制比例
  • 多边形

线条末端样式

通过画布的渲染上下文对象lineCap属性可指定线路末端样式,其API如下所示:

属性值说明
butt线段末端以方形结束
round线段末端以圆形结束
square线段末端以方形结束
ctx.lineCap = "butt";
ctx.lineCap = "round";
ctx.lineCap = "square";

运行效果如下图所示:

在这里插入图片描述

线段的末端样式规则为:

  • round: 增加了一个半径等于线路宽度一半的半圆
  • square: 增加了一个宽度和线段宽度相同,长度是线段宽度一半的矩形区域

其完整源代码如下:

<!DOCTYPE html>
<html lang="cn">
<head>
    <title>渲染效果(stroke)</title>
    <meta charset="UTF-8">
    <script src="./js/helper.js"></script>
</head>

<body style="overflow: hidden; margin:10px; background-color: white;">
    <canvas id="canvas" width="750" height="300" style="border:solid 1px #CCCCCC;"></canvas>
</body>
<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画布中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);
    
    // 指定线宽
    ctx.lineWidth = 20;

    // ctx.lineCap 默认值(butt);
    ctx.beginPath();
    ctx.moveTo(50, 50);
    ctx.lineTo(450, 50);
    ctx.stroke();

    // ctx.lineCap = "butt";
    ctx.beginPath();
    ctx.moveTo(50, 110);
    ctx.lineTo(450, 110);
    ctx.lineCap = "butt";
    ctx.stroke();

    // ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(50, 170);
    ctx.lineTo(450, 170);
    ctx.lineCap = "round";
    ctx.stroke();

    // ctx.lineCap = "square";
    ctx.beginPath();
    ctx.moveTo(50, 230);
    ctx.lineTo(450, 230);
    ctx.lineCap = "square";
    ctx.stroke();
</script>

</html>

线条连接风格

通过画布的渲染上下文对象lineJoin属性可指定线路末端样式,其API如下所示:

ctx.lineJoin = "bevel";
ctx.lineJoin = "round";
ctx.lineJoin = "miter";
属性值说明
bevel在相连部分的末端填充一个额外的以三角形为底的区域,每个部分都有各自独立的矩形拐角。
round通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。圆角的半径是线段的宽度。
miter通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

运行效果如下图所示:

在这里插入图片描述

其源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);

    // 指定线宽
    ctx.lineWidth = 40;

    // ctx.lineJoin = "bevel";
    ctx.beginPath();
    ctx.moveTo(50, 70);
    ctx.lineTo(220, 120);
    ctx.lineTo(50, 170);
    ctx.lineJoin = "bevel";
    ctx.stroke();

    // ctx.lineJoin默认值(miter)
    ctx.beginPath();
    ctx.moveTo(320, 70);
    ctx.lineTo(490, 120);
    ctx.lineTo(320, 170);
    ctx.lineJoin = "round";
    ctx.stroke();

    // ctx.lineJoin = "round";
    ctx.beginPath();
    ctx.moveTo(590, 70);
    ctx.lineTo(760, 120);
    ctx.lineTo(590, 170);
    ctx.lineJoin = "miter";
    ctx.stroke();
</script>

闭合多边形

在讲解绘制曲线和路径时我们提到过,在绘制多边形时,可通过ctx.closePath()闭合一个多边形,有时也会通过ctx.moveTo()到起始点的坐标闭合一个多边形。这两种方法均可实现闭合一个多边形,但在设置了lineJoin属性后,其运行结果会有所差异,如下图所示:

在这里插入图片描述

从上图可以看出,使用ctx.closePath()闭合多边形才会更符合我们所希望的效果。

2. 阴影

阴影颜色和模糊程度

通过画布的渲染上下文对象shadowBlur属性和shadowColor可指定线路末端样式,其API如下所示:

ctx.shadowBlur = level;
ctx.shadowColor = color;
属性说明
shadowBlur描述模糊效果程度的,float 类型的值。注意:只有设置 shadowColor 属性值为不透明,阴影才会被绘制。
shadowColor可以转换成 CSS 值的DOMString 字符串。默认值是 fully-transparent black.。

下图是设置了该属性的运行效果:

在这里插入图片描述

其源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格线
    drawGrid('lightgray', 10, 10);

    // 设置阴影效果
    ctx.shadowBlur = 30;
    ctx.shadowColor = "red";
    
    // 开始绘制路径
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2 * Math.PI)
    ctx.ellipse(300, 100, 75, 50, 0, 0, 2 * Math.PI);
    ctx.rect(450, 50, 200, 100);
    ctx.fillStyle = "green";
    ctx.fill();
</script>

阴影偏移

在设置阴影效果时,除了阴影颜色和模糊程度外,还可设置阴影的偏移距离,其API如下:

ctx.shadowOffsetX = offset;
ctx.shadowOffsetY = offset;
属性说明
shadowOffsetX阴影水平偏移距离的 float 类型的值。默认值是 0。
shadowOffsetY阴影垂直偏移距离的 float 类型的值。默认值是 0。

下图是设置了该属性的运行效果:

在这里插入图片描述

其源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格线
    drawGrid('lightgray', 10, 10);

    // 设置阴影效果
    ctx.shadowBlur = 30;
    ctx.shadowColor = "red";
    
    // 开始绘制路径
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2 * Math.PI)
    ctx.ellipse(300, 100, 75, 50, 0, 0, 2 * Math.PI);
    ctx.rect(450, 50, 200, 100);
    ctx.fillStyle = "green";
    ctx.fill();

    ctx.translate(0, 160);
    // 设置阴影效果
    ctx.shadowOffsetX = 10;
    ctx.shadowOffsetY = 10;
    // 开始绘制路径
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2 * Math.PI)
    ctx.ellipse(300, 100, 75, 50, 0, 0, 2 * Math.PI);
    ctx.rect(450, 50, 200, 100);
    ctx.fillStyle = "green";
    ctx.fill();

    ctx.translate(0, 160);
    // 设置阴影效果
    ctx.shadowOffsetX = -10;
    ctx.shadowOffsetY = 10;
    // 开始绘制路径
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2 * Math.PI)
    ctx.ellipse(300, 100, 75, 50, 0, 0, 2 * Math.PI);
    ctx.rect(450, 50, 200, 100);
    ctx.fillStyle = "green";
    ctx.fill();
</script>

3. 渐变

\quad 在之前的内容中,我们使用过ctx.strokeStyle=colorctx.fillStyle=color设置绘制图形时的边框颜色和填充颜色,其实这两个属性除了可以指定颜色之外,还可以指定为渐变对象填充图案对象,这一节我们讲解设置渐变风格的实现过程。

\quad 渐变风格又包括了“线性渐变”和“径向渐变”两种不同的风格。

线性渐变

\quad 线性渐变是一种颜色过渡方式,它以一条直线(水平或垂直)为轴线,从起点到终点颜色进行顺序渐变。渲染上下文对象提供了建立线性渐变的方法,其定义如下:

CanvasGradient ctx.createLinearGradient(x0, y0, x1, y1);
参数说明
x0起点的 x 轴坐标
y0起点的 y 轴坐标
x1终点的 x 轴坐标
y1终点的 y 轴坐标

\quad 该方法的返回值是一个CanvasGradient对象,该对象包含了一个方法:

void gradient.addColorStop(offset, color);
参数说明
offset偏移位置,0到1之间的值
color颜色值

\quad 我们通过一个例子熟悉一下线性渐变的用法,运行效果如下:

在这里插入图片描述

\quad 这个例子使用了线性渐变填充在圆形、矩形和文本。起始颜色是金色(gold),终止颜色是红色(red),其源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);

    // 建立线性渐变,其坐标相对于画布的坐标
    const gradient = ctx.createLinearGradient(0, 50, 0, 200);
    gradient.addColorStop(0.05, "gold");
    gradient.addColorStop(0.95, "red");
    ctx.fillStyle = gradient;

    // 绘制圆
    ctx.beginPath();
    ctx.arc(125, 125, 75, 0, 2 * Math.PI);
    ctx.fill();

    // 绘制矩形
    ctx.translate(200, 0);
    ctx.beginPath();
    ctx.rect(50, 50, 150, 150);
    ctx.fill();

    // 绘制文字
    ctx.translate(250, 0);
    ctx.font = "150px 黑体"
    ctx.textBaseline = "top";
    ctx.fillText("图形", 0, 50);
</script>

\quad 在这个例子中建立的线性渐变对象,其坐标为(0,50)至(0,200),表示其渐变颜色的方向为从上往下垂直渐变。改变坐标就能改变颜色逐渐变换的方向,例如可以改为水平方向,也可以改为沿着斜线的方向。我们看看下面这个示例:
在这里插入图片描述

\quad 渐变对象的addColorStop()方法用于指定渐变颜色,该方法可以调用n次,第一次表示渐变开始的颜色,第二次表示渐变结束的颜色,第三次会以第二次为开始颜色渐变,以此类推。我们看看下面这个示例:

在这里插入图片描述

其源代码如下:

// 建立线性渐变,其坐标相对于画布的坐标
const gradient = ctx.createLinearGradient(0, 50, 0, 200);
gradient.addColorStop(0.05, "red");
gradient.addColorStop(0.5, "gold");
gradient.addColorStop(0.95, "green");
ctx.fillStyle = gradient;

径向渐变

径向渐变是指从起点到终点颜色从内到外进行圆形渐变(从中间向外拉)。渲染上下文对象提供了建立径向渐变的方法,其定义如下:

CanvasGradient ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
参数说明
x0开始圆形的 x 轴坐标
y0开始圆形的 y 轴坐标
r0开始圆形的半径
x1结束圆形的 x 轴坐标
y1结束圆形的 y 轴坐标
r1结束圆形的半径

\quad 该方法的返回值是一个CanvasGradient对象,该对象包含了方法addColorStop()与线性渐变的该方法完全一样。接下来看一个径向渐变的例子,运行效果如下:

在这里插入图片描述

\quad 径向渐变同样可填充在圆形、矩形和文本等图形中。从上图可知径向渐变是一种颜色从内到外的渐变,从一个起点向所有方向进行的渐变。完整源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);

    // 建立径向渐变,其坐标相对于画布的坐标
    const gradient = ctx.createRadialGradient(125, 125, 0, 125, 125, 160);
    gradient.addColorStop(0.05, "gold");
    gradient.addColorStop(0.95, "red");
    ctx.fillStyle = gradient;

    // 绘制圆
    ctx.beginPath();
    ctx.arc(125, 125, 75, 0, 2 * Math.PI);
    ctx.fill();

    // 绘制矩形
    ctx.translate(200, 0);
    ctx.beginPath();
    ctx.rect(50, 50, 150, 150);
    ctx.fill();

    // 绘制文字
    ctx.translate(250, 0);
    ctx.font = "150px 黑体"
    ctx.textBaseline = "top";
    ctx.fillText("图形", 0, 50);
</script>

重要提示:渐变对象可同时应用于多个形状或文字,该示例中的圆形、矩形和文字均使用了该渐变对象。在绘制了圆形之后,由于使用了translate()将画布坐标系进行了偏移,在绘制矩形和文字时的坐标仍与绘制圆的坐标位置基本一致,因此该渐变对象的坐标可同时适用于此三个形状/文字。关于translate()的用法我们将在后续的章节中进行介绍。

\quad 使用createRadialGradient()创建径向渐变对象时可指定开始圆的位置和半径,也可指定结束圆的位置和半径,下面的效果图片就是改变了这几个参数后的运行效果,如下图:

在这里插入图片描述

4. 图案/纹理

\quad 除了渐变对象外,fillStyle还可以使用图案/纹理方式填充各类图形,使得画布可以很方面的实现类似于CAD等绘图软件提供的图案填充功能。渲染上下文对象提供了创建图案的方法createPattern(),其定义如下:

CanvasPattern ctx.createPattern(image, repetition);
参数说明
image填充图案源
repetition重复方式
  • 填充图案源可以是位图、也可以是的画布对象
  • 重复方式包括:
    • “repeat” :水平和垂直方向均重复
    • “repeat-x” :仅水平方向重复
    • “repeat-y” :仅垂直方向重复
    • “no-repeat” :不重复
      默认值是:repeat

使用位图作为填充图案

\quad 填充图案亦可应用于路径、矩形和文字中,下面这个示例将在圆形、矩形和文本绘制中使用图案填充,其效果如下所示:

在这里插入图片描述

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);

    // 装载图案后,渲染图形
    loadImage("./images/15.jpg", function (image) {
        let pattern = ctx.createPattern(image, "repeat");
        ctx.save();
        
        // 设置图案填充样式
        ctx.fillStyle = pattern;
        // 设置描边时的线宽
        ctx.lineWidth = 2;
        
        // 绘制带图案填充的圆
	    ctx.beginPath();
	    ctx.arc(125, 125, 75, 0, 2 * Math.PI);
	    ctx.fill();
	    ctx.stroke();
	
	    // 绘制带图案填充的矩形
	    ctx.translate(200, 0);
	    ctx.beginPath();
	    ctx.rect(50, 50, 150, 150);
	    ctx.fill();
	    ctx.stroke();
	
	    // 绘制带图案填充的文字
	    ctx.translate(250, 0);
	    ctx.font = "150px 黑体"
	    ctx.textBaseline = "top";
	    ctx.fillText("图形", 0, 50);
        ctx.strokeText("图形", 0, 50);
        ctx.restore();
    })

    function loadImage(src, callback) {
        // 加载并绘制图片
        let image = new Image();
        image.onload = function () {
            callback(image);
        }
        image.src = src
    }
</script>

\quad 在图形系统中,经常应用“填充图案”描述图形中一些特殊的区域或者材质,如下图所示:

在这里插入图片描述

使用画布作为填充图案

\quad 除了直接使用位图作为填充图案之外,还可以使用画布的内容作为填充图案,比较适合一些使用简易图案作为填充图案的场景,下面这个示例展示了使用画板作为填充图案,运行效果如下图所示:

在这里插入图片描述

\quad 在这个示例中,使用document.createElement("canvas")创建了一个临时画布,在这个画布中绘制了两个线条,并使其重复填充至主画布的圆形和矩形中,就实现了上面这个效果,其完整源代码如下:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 绘制背景网格
    drawGrid('lightgray', 10, 10);
    // 设置样式
    ctx.fillStyle = getParrent(25, 25);
    ctx.lineWidth = 2;
    
    // 绘制带图案填充的圆
    ctx.beginPath();
    ctx.arc(130, 125, 100, 0, 2 * Math.PI);
    ctx.fill();
    ctx.stroke();

    // 绘制带图案填充的矩形
    ctx.translate(220, 0);
    ctx.beginPath();
    ctx.rect(50, 50, 500, 180);
    ctx.fill();
    ctx.stroke();

    /**
     * 建立画布填充图案对象
     */
    function getParrent(width, height) {
        // 创建临时画布
        let pcanvas = document.createElement("canvas");
        pcanvas.width = width;
        pcanvas.height = height;
        pctx = pcanvas.getContext('2d');
        // 绘制线条
        pctx.beginPath();
        pctx.moveTo(0, 0);
        pctx.lineTo(width, height);
        pctx.moveTo(width, 0);
        pctx.lineTo(0, height);
        pctx.strokeStyle = "blue";
        pctx.lineWidth = 0.5;
        pctx.stroke();

        return ctx.createPattern(pcanvas, "repeat");
    }
</script>

掌握了使用渐变和图案作为填充效果之后,接下来我们看一个“围棋”实际案例,该围棋棋盘和棋子的绘制效果非常逼真,如下图所示:

在这里插入图片描述

在该示例中,使用“图案填充”技术填充了围棋棋盘,使用“径向渐变”实现了棋子的光影效果,这两种技术都是我们刚刚讲述过的,因此其实现的代码也很容易理解,如下所示:

<script>
    // 从页面中获取画板对象
    let canvas = document.getElementById('canvas');
    // 从画板中获取“2D渲染上下文”对象
    let ctx = canvas.getContext('2d');
    // 棋盘格子大小
    let size = 100;

    // 使用木质纹理图案作为围棋棋盘
    let image = new Image();
    image.onload = function () {
        draw();
    }
    image.src = "./images/wood2.png";

    /**
     * 绘制棋盘和棋子
     */
    function draw() {
        let pattern = ctx.createPattern(image, "repeat");
        ctx.save();
        // 绘制带图案填充的圆和矩形
        ctx.fillStyle = pattern;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.restore();

        // 绘制背景网格
        drawGrid('lightgray', 10, 10);

        // 绘制棋盘
        drawBoards();

        // 绘制棋子(第3个参数为棋子类型: 1是为黑子,0为白子)
        drawPiece(2, 1, 1);
        drawPiece(3, 0, 1);
        drawPiece(3, 1, 1);
        drawPiece(2, 1, 1);
        drawPiece(0, 2, 1);
        drawPiece(1, 2, 1);
        drawPiece(2, 2, 1);
        drawPiece(3, 2, 0);
        drawPiece(4, 0, 0);
        drawPiece(4, 1, 0);
        drawPiece(0, 3, 0);
        drawPiece(1, 3, 0);
        drawPiece(2, 3, 0);
        drawPiece(3, 3, 0);
    }

    /**
     * 绘制棋盘函数
     */
    function drawBoards() {
        ctx.save();
        ctx.beginPath();
        ctx.lineCap = "square";
        for (let i = size; i < canvas.width; i += size) {
            ctx.moveTo(i, size);
            ctx.lineTo(i, canvas.height)
        }
        for (let i = size; i < canvas.width; i += size) {
            ctx.moveTo(size, i);
            ctx.lineTo(canvas.width, i)
        }
        ctx.lineWidth = 6;
        ctx.stroke();
        ctx.restore();
    }
    
    /**
     * 绘制棋子函数
     */
    function drawPiece(x, y, type) {
        // 计算棋子的坐标
        x = (x + 1) * 100;
        y = (y + 1) * 100;
        let radius = size/2 - 2;

        // 建立径向渐变,其坐标相对于画布的坐标	
        const gradient = ctx.createRadialGradient(x + radius / 2, y - radius / 2, 0, x, y, radius);
        // type == 1是为黑子,否则为白子
        gradient.addColorStop(0, type == 1 ? "#B9B9B9" : "#FFFFFF");
        gradient.addColorStop(0.95, type == 1 ? "#000000" : "#DCDCDC");
        gradient.addColorStop(0.97, type == 1 ? "#000000" : "#DCDCDC00");
        gradient.addColorStop(1, type == 1 ? "#00000000" : "#DCDCDC00");

        // 绘制圆
        ctx.save();
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, 2 * Math.PI);
        ctx.fillStyle = gradient;
        ctx.fill();
        ctx.restore();
    }
</script>

5. 本章小结

\quad 本章讲解了Canvas所提供的的一些渲染效果的用法,这些效果不仅仅是增强了图形的立体感和视觉效果,更重要的是让图形更具有真实感,使图形看起来更接近现实世界,因此这些这些效果在图形系统中得到了广泛应用。

本章内容使用了Canvas 2D API以下属性和方法:

属性

属性值说明
ctx.lineCap线条末端样式
ctx.lineJoin线条连接风格
ctx.shadowBlur模糊程度
ctx.shadowColor阴影颜色
ctx.shadowOffsetX阴影水平偏移距离
ctx.shadowOffsetY阴影垂直偏移距离

方法

方法名说明
ctx.createLinearGradient(x0, y0, x1, y1)创建线性渐变样式
ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)创建径向渐变样式
gradient.addColorStop(offset, color)添加一个由偏移值和颜色值指定的断点到渐变
ctx.createPattern(image, repetition)创建填充图像样式

练习一下

阴影

按照以下格式要求在Canvas中绘制你喜欢的一本书的名字:

  • 垂直居中
  • 水平居中
  • 字体大小:50px
  • 字型:黑体
  • 颜色:blue
  • 添加阴影效果
渐变和图案

\quad 在本章渐变与图案的示例中,均是将这两种风格应用在了填充样式ctx.fillStyle中,而且示例中的几何对象也是几个简单的几何对象。其实渐变与图案是可以应用于更复杂的路径,同时还可以应用于描边样式ctx.strokeStyle的,下面这张图片就是将渐变和图案应用到了贝塞尔曲线中了。

在这里插入图片描述

你也动手试一试吧。

相关资料

系列教程及代码资料:https://GraphAnyWhere.com
图形系统开发实战课程:基础篇——图形系统概述
图形系统开发实战课程:基础篇——1.绘制基本图形
图形系统开发实战课程:基础篇——2.绘制文字
图形系统开发实战课程:基础篇——3.绘制图像
图形系统开发实战课程:基础篇——4.绘制曲线和路径


作者信息

作者 : 图形开发学院
CSDN: https://blog.csdn.net/2301_81340430?type=blog
官网:https://graphanywhere.com

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值