H5 Canvas画布基础 一

     画布元素可被用来通过JavaScript(Canvas API 或 WebGL API)绘制图形及图形动画。
     本文为H5 画布学习笔记。

基本用法

  1. canvas 需要有闭合标签</ canvas >。

  2. 画布大小在标签中可以直接指定,或者使用JavaScript指定。   也可以使用CSS指定高度和宽度。在渲染的过程中< canvas >元素中的内容会根据情况缩放来适应需要的大小。
    注意:画布元素不可以使用CSS控制样式。

  3. canvas绘制是同步的,代码执行有别于浏览器本身渲染机制,样式定义必须在绘制之前。

  4. 画布具有覆盖渲染的效果。

  5. 最大画布尺寸

浏览器最大高度最大宽度最大面积
Chorme32,767 px32,767 px268,435,456 px
Firefox32,767 px32,767 px742,907,776 px
Safari32,767 px32,767 px268,435,456 px
IE819,2px819,2px?
  1. 使用示例
<canvas id="canvas" width="300" height="300">
抱歉,您的浏览器不支持canvas元素
(标签内内容会在不支持<canvas>元素的浏览器或是禁用了JavaScript的浏览器内渲染并展现)
</canvas>

矩形绘制

  1. 绘图上下文
<script type="text/jscript">
	window.onload = function(){
		// 用querySelector拿到画布
		var canvas = document.querySelector("#test");
		if(canvas.getContext){
		// 画布调用,需要先判断是否存在
		  var ctx = canvas.getContext("2d");
		}
	}	
</script>
  1. 绘制填充矩形
  // 填充矩形绘制(x,y,width,height)
  ctx.fillRect(0,0,100,100)
  1. 绘制边框矩形
 // 填充矩形绘制(x,y,width,height)
 ctx.strokeRect(100,100,100,100)
  1. 绘制透明清除矩形
 //清除指定矩形区域,让清除部分完全透明
 ctx.clearRect (100,100,100,100)
  1. 使用画布绘制边框矩形时,渲染如上代码:
    而渲染宽度默认为1px的情况下,矩形边框经过放大可以看到并非是1px而是2px

在这里插入图片描述
在渲染位置为100的边框线时,渲染范围是99.5-100.5像素,而再经过向上取整即实际渲染范围为99-101
若要绘制1px边框。我们需要指定渲染位置为100.5即可

 // 填充矩形绘制
ctx.fillRect(0,0,100,100)
// 边框矩形绘制
ctx.strokeRect(100.5,100.5,100,100)

效果:
在这里插入图片描述
9. 添加样式和颜色

// 设置图形填充颜色
ctx.fillStyle = "deeppink";
//设置图形轮廓颜色
/**默认线条和填充均为黑色,颜色值#000000 **/
ctx.strokeStyle = "pink";
//设置边框宽度 默认值1.0
/**属性必须为正值,0、负数、Infinity和NaN会被忽略**/
ctx.lineWidth = 10;
//线条样式LineJoin round圆角 bevel斜角 miter直角
ctx.lineJoin = "round";

路径绘制

路径即点的集合。闭合路径可以得到图形。绘制路径的时候需要定义点的集合,即描点。

  1. 尝试绘制三角形
    实例代码:
//路径描点
//将笔触移动到指定位置x,y,会抬起画笔
ctx.moveTo(10,10);
//定义一条当前笔触位置到x,y的直线
ctx.lineTo(50,100);
ctx.lineTo(100,100);
//闭合路径,此次相当于ctx.lineTo(10,10);
ctx.closePath();
//绘制线条,不会自动闭合路径,需要closePath
ctx.stroke();
//填充图形,会自动闭合路径,不需要closePath
ctx.fill();
//清空路径容器
/**定义的路径被存储在路径容器中,
绘制时读取**/
ctx.beginPath();
ctx.moveTo(110,110);
ctx.lineTo(150,50);
ctx.lineTo(200,250);
ctx.closePath();
ctx.stroke();

绘制效果:

在这里插入图片描述

  1. moveTo抬起笔触效果
//moveTo会抬起画笔
ctx.moveTo(10,10);
ctx.lineTo(50,100);
ctx.lineTo(100,100);
ctx.closePath();
  			
ctx.moveTo(110,110);
ctx.lineTo(150,50);
ctx.lineTo(200,250);
ctx.closePath();
ctx.stroke();

绘制效果:
在这里插入图片描述
2. 线段末端

//线段末端形状 默认为butt方形;square方形,round圆角
/**square和round为在末端添加了一段宽度和线段相同,高度为线段一半的矩形区域**/
ctx.lineCap = "butt";

Save & Restore

  • Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
  • Canvas 状态是以堆(stack)的方式保存的。每一次调用save()方法,当前的状态就会被保存进堆中(类似数组的push());而每一次调用restore()方法,就会将当前状态从堆中移除(类似数组的pop())。这种状态包括 :
       当前应用的变形(即移动,旋转和缩放)
       当前的裁切路径(使用clip()方法裁切)
       strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit,   shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation,font,textAlgin和textBaseline的值.

    你可以调用任意多次 save ()方法。 每一次调用 restore() 方法,上一个保存的状态就从堆中弹出,所有设定都恢复。

canvas 签名画板

实现一个canvas鼠标移动绘制的实例。

window.onload = function(){
	//画布获取
	var canvas = document.getElementById("test");
	if(canvas.getContext){
		var ctx = canvas.getContext("2d");
	}
	//点击事件
       canvas.onmousedown = function(ev){
	   ev = ev || window.event;
	   //全局捕获(ie适配)
	   if(canvas.setCapture){
		canvas.setCapture();
		}
		//点击后移动绘点
		ctx.beginPath();
		ctx.moveTo(ev.clientX - canvas.offsetLeft,ev.clientY - canvas.offsetTop);
		//点击时鼠标移动
		document.onmousemove = function(ev){
		ev = ev || event;
		ctx.lineTo(ev.clientX - canvas.offsetLeft,ev.clientY - canvas.offsetTop);
		ctx.stroke();
		}
		document.onmouseup = function(){
			document.onmousemove = document.onmouseup = null;
			if(document.releaseCapture){
				document.releaseCapture();
				}
			}
		return false;
		}
	}

效果:
在这里插入图片描述

canvas 曲线

角度与弧度的表达式 radians = (Math.PI/180)*degress

  1. 方法:arc(x,y,radius,startAngle,endAngle,anticlockwise)
    在这里插入图片描述

示例:

<script type="text/jscript">
		window.onload = function(){
			//画布获取
			var canvas = document.getElementById("test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				ctx.beginPath();
				ctx.moveTo(100,100);
				//画一个以x,y 为圆心以radius为半径的圆弧,从startAngle开始到endAngle结束,
				//anticlockwise给定方向,true 逆时针,false 顺时针
				ctx.arc(100,100,80,0,310*Math.PI/180,true);
				
				ctx.closePath();
				ctx.stroke();
			}
		}
	</script>

结果:
在这里插入图片描述

  1. 方法:arcTo(x1,y1,x2,y2,radius)
    在这里插入图片描述

示例:绘制圆角

<script type="text/jscript">
		window.onload = function(){
			//画布获取
			var canvas = document.getElementById("test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				
				ctx.beginPath(); 
				ctx.moveTo(20,20);           // 创建起始点
				ctx.lineTo(100,20);          // 创建水平线 
				ctx.arcTo(150,20,150,70,50); //创建以50为半径的圆弧
				ctx.lineTo(150,150);  //画竖线
				ctx.stroke();
			}
		}
	</script>

效果:
在这里插入图片描述

  1. 二次贝塞尔曲线

方法:ctx.quadraticCurveTo(cpx,cpy,x,y);
在这里插入图片描述
示例:

if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				/***二次贝塞尔曲线,必过两个控制点***/
				ctx.beginPath();
				ctx.moveTo(20,20);//起始点
				ctx.quadraticCurveTo(20,100,200,20);//控制点(20,100),结束点(200,20)
				ctx.stroke();
			}

结果:在这里插入图片描述

  1. 三次贝塞尔曲线

方法:ctx.bezierCurveTo(cpx,cpy,x,y);
在这里插入图片描述
示例:

ctx.beginPath();
ctx.moveTo(20,20);//起始点
//控制点1(20,100),控制点2(200,100),结束点(200,20)
ctx.bezierCurveTo(20,100,200,100,200,20);
ctx.stroke();

结果
在这里插入图片描述

canvas 变换

   画布中的元素无法通过css控制变换,画布元素本身是一个DOM节点。

  1. Translate(x,y)-移动
    与css中不同的是画布中Translate进行累加操作而非覆盖操作。
    它用来移动canvas原点的位置,接收x,y两个偏移量参数。
  2. Rotate(angle)-旋转
    接收一个角度参数,顺时针方向以弧度为单位的旋转角度,旋转中心为Canvas原点。
  3. Scale(x,y)-缩放
    接收两个值,缩放因子x,y。缩放因子为1.0表示不进行缩放,比1.0小即为缩小,比1.0大即为放大。
    注意:如果缩放绘图,所有未来的绘图也将被缩放。定位也将被缩放。如果按比例缩放(2,2),则绘图的位置是画布左边和顶部的两倍。

示例:

/***移动&旋转***/
ctx.translate(100, 100);//原点移动到(100,100)
ctx.rotate(45*Math.PI/180);	//顺时针旋转45°
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.fillRect(0,0,100,100);
/***缩放***/
ctx.translate(70, 70);//原点移动到(100,100)
ctx.fillStyle = "blue";
ctx.fillRect(0,0,100,100);
ctx.fillStyle = "pink";
ctx.scale(0.5,0.5);
ctx.fillRect(0,0,100,100);

在这里插入图片描述
实例1:旋转缩放动画

<script type="text/jscript">
		window.onload = function() {
			//画布获取
			var canvas = document.getElementById("test");
			if (canvas.getContext) {
				var flag = 0,angle = 0,temp;
				var ctx = canvas.getContext("2d");
				ctx.save();
				setInterval(function(){
					angle++ ;
					ctx.clearRect(0,0,canvas.width,canvas.height)
					ctx.save()
					ctx.translate(150,150)
					ctx.rotate(angle*Math.PI/180)
					if( flag == 100){ temp = -1 }
					else if(flag == 0){ temp = 1}
					flag += temp;
				    ctx.scale(flag*0.01,flag*0.01)
					ctx.beginPath()
					ctx.fillRect(-50,-50,100,100)
					ctx.restore()
				},1500/144) 
				ctx.restore()
			}
		}
	</script>

在这里插入图片描述

canvas-实例1(变换) :钟表

画布在高分辨率屏幕上模糊的解决方法
源码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				margin: 0;
				padding: 0;
			}
			html,
			body {
				height: 100%;
				overflow: hidden;
			}
			body {
				background-color: darksalmon;
			}
			#clock {
				background-color: black;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="clock" height="800" width="800" style="width: 400px ;height: 400px;">
			<span>不支持canvas</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload = function() {
			//画布获取
			var clock = document.getElementById("clock");
			if (clock.getContext) {
				var ctx = clock.getContext("2d");
				ctx.translate(400,400)
				//定时器每秒刷新2次
				setInterval(function(){
					ctx.clearRect(-400,-400,800,800);//每次绘制完清除画布
					/*************表盘**************/
					//分针刻度
					//刻度线条样式
					ctx.strokeStyle = "#3E3E3E";
					ctx.lineCap = "square";
					ctx.lineWidth = 2;
					ctx.save()
					for(var i=0;i<60;i++){
						ctx.rotate(6*Math.PI/180)
						ctx.beginPath();
						ctx.moveTo(236,0);
						ctx.lineTo(240,0);
						ctx.stroke()
					}
					ctx.restore();
					//时针刻度
					//刻度线条样式
					ctx.strokeStyle = "white";
					ctx.lineCap = "square";
					ctx.lineWidth = 4;
					ctx.save()
					for(var i=0;i<12;i++){
						ctx.rotate(30*Math.PI/180)
						ctx.beginPath();
						ctx.moveTo(230,0);
						ctx.lineTo(240,0);
						ctx.stroke()
					}
					ctx.restore();
					//中轴
					ctx.save()
					ctx.lineWidth = 7;
					ctx.beginPath()
					ctx.arc(0,0,8,0,360*Math.PI/180)
					ctx.cl
					ctx.stroke()
					ctx.restore();
					//获取时间
					var mydate = new Date;
					var second = mydate.getSeconds();     //获取当前秒数(0-59)
					var min = mydate.getMinutes() + second/60;     //获取当前分钟数(0-59)
					var hour = mydate.getHours()+min/60;       //获取当前小时数(0-23)
					hour = hour>12?hour-12:hour;
					/*************指针*************/
					ctx.save()
					//时钟指针
					ctx.save()
					ctx.fillStyle = "#E9967A";
					ctx.lineWidth = 1;
					ctx.beginPath()
					ctx.rotate(hour*30*Math.PI/180)
					ctx.scale(0.5,0.5)
					ctx.moveTo(3,-20)
					ctx.lineTo(3,-40)
					ctx.lineTo(8,-50)
					ctx.lineTo(8,-225)
					ctx.lineTo(0,-240)
					ctx.lineTo(-8,-225)
					ctx.lineTo(-8,-50)
					ctx.lineTo(-3,-40)
					ctx.lineTo(-3,-20)
					ctx.fill()
					ctx.restore()
					//分针刻度
					ctx.save()
					ctx.fillStyle = "white";
					ctx.lineWidth = 1;
					ctx.beginPath()
					ctx.rotate(min*6*Math.PI/180)
					ctx.scale(0.5,0.5)
					ctx.moveTo(3,-20)
					ctx.lineTo(3,-40)
					ctx.lineTo(8,-50)
					ctx.lineTo(8,-365)
					ctx.lineTo(0,-380)
					ctx.lineTo(-8,-365)
					ctx.lineTo(-8,-50)
					ctx.lineTo(-3,-40)
					ctx.lineTo(-3,-20)
					ctx.fill()
					ctx.restore()
					//秒针刻度
					ctx.save()
					ctx.fillStyle = "beige";
					ctx.lineWidth = 1;
					ctx.beginPath()
					ctx.rotate(second*6*Math.PI/180)
					ctx.scale(0.5,0.5)
					ctx.moveTo(3,60)
					ctx.lineTo(3,-40)
					ctx.lineTo(2,-50)
					ctx.lineTo(2,-400)
					ctx.lineTo(0,-410)
					ctx.lineTo(-2,-400)
					ctx.lineTo(-2,-50)
					ctx.lineTo(-3,-40)
					ctx.lineTo(-3,60)
					ctx.fill()
					ctx.restore()
					ctx.restore()
				},1000/2)
			}
		}
	</script>
</html>

效果:时钟

图片

(以200x200图片为例,画布大小400X400)

  1. 在画布上插入图片
    drawImage(img,x,y,width,height)
<script type="text/javascript">
	window.onload = function() {
		//画布获取
		var canvas = document.getElementById("test");
		if (canvas.getContext) {
			var ctx = canvas.getContext("2d");
			//图片对象
				
			var img =  new Image();
			img.src = "../img/Aulac10622_square.jpg"
			img.onload = function(){
				draw();
			}
			function draw(){
				//插入图片(图片,位置,大小)
				ctx.drawImage(img,0,0,200,200)
			}
		}
	}
</script>
  1. 使用图片填充背景
    createPattern(img,“repetition”),其中repetition取值如下图
var pattern = ctx.createPattern(img,"repeat");
ctx.fillStyle = pattern;
ctx.fillRect(0,0,400,400)

在这里插入图片描述

  1. 渐变填充背景
    线性渐变
           渐变实际上是两种或多种颜色之间的平滑过渡。而线性渐变是多种颜色沿着一条直线 (称为渐变线)过渡。
           渐变的实现由两部分组成:渐变线和色标。渐变线用来控制发生渐变的方向;色标包含一个颜色值和一个位置,用来控制渐变的颜色变化。浏览器从每个色标的颜色淡出到下一个,以创建平滑的渐变,通过确定多个色标可以制作多色渐变效果。
    径向渐变
           径向渐变使用 createRadialGradient 方法创建一个指定了开始和结束圆的 CanvasGradient 对象。绘制了一系列从中心点放射到边缘形状的同心圆。
/******线性渐变******/
//线性渐变起始点和结束点,渐变线
 var g = ctx.createLinearGradient(0,0,400,400)
//(offset:偏移量,css有效颜色值)色标
g.addColorStop(0,"#FFA113")
g.addColorStop(0.5,"#FF8214")
g.addColorStop(1,"#FF1F3E")
ctx.fillStyle = g;
ctx.fillRect(0,0,400,400)

/******径向渐变******/
//径向渐变前三个参数定义一个x1,y1,r1的圆,
//后三个参数定义一个x2,y2,r2的圆
var g = ctx.createRadialGradient(200,200,100,200,200,200)
//(offset:偏移量,css有效颜色值)
g.addColorStop(0,"#FFA113")
g.addColorStop(0.5,"#FF8214")
g.addColorStop(1,"#FF1F3E")
ctx.fillStyle = g;
ctx.fillRect(0,0,400,400)

在这里插入图片描述

文本

  1. 文本有两种绘制方法

    fillText(“text”,x,y,maxwidth)
    strokeText(“text”,x,y,maxwidth)

    当maxwidth < 文本原始宽度时会压缩字符间距
    在这里插入图片描述

  2. 文本样式
    字体样式指定 font = “size fontname”
    文本对齐 textAligin = “mode”
    文本基线 textBaseline 取值见下图 默认值为alphabetic
    与css不同,画布中文本相对于x坐标(示例为200)进行对齐操作

在这里插入图片描述
在这里插入图片描述

//canvas仅支持一种字体:sans-serif
ctx.font = "12px sans-serif"		
ctx.fillStyle = "#00BFFF"
ctx.fillText("Definiteness of purpose is the starting point of all achievement.",200,100,400)

ctx.font = "30px sans-serif"
ctx.textAlign  = "center"
ctx.strokeText("Definiteness",200,200,800)
 
  1. 文本水平居中
    measureText(“text”)返回一个TextMetrics值。
    使用此方法可以对文本进行水平居中:
 ctx.fillText("text",(ctx.width - textwith)/2,ctx.height-fontsize,maxwidth)

在这里插入图片描述
4. 文本阴影

  • shadowColor:阴影颜色(必需项)
  • shadowOffsetX :阴影x轴偏移量(延伸距离)
  • shadowOffsetY阴影Y轴偏移量(延伸距离)
  • shadowBlur: 阴影模糊程度
ctx.font = "30px sans-serif"
ctx.shadowColor = "deepskyblue"
ctx.shadowOffsetX  = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 3;
ctx.textBaseline = "top"
ctx.fillText("Definiteness",100,100,800)

在这里插入图片描述

像素操作

  1. ImageData对象
        ImageData对象中存储着canvas对象真实的像素数据,它包含以下几个只读属性:
        width 图片宽度,单位是像素
        height 图片高度,单位是像素 data 包含着RGBA格式的整型数据,范围在0至255之间(包括255)。
    我们具体来看看data属性:
        data 属性返回一个对象,该对象包含指定的 ImageData 对象的图像数据。
        对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:
        R - 红色(0-255)
        G - 绿色(0-255)
        B - 蓝色(0-255)
        A - alpha 通道(0-255; 0 是透明的,255 是完全可见的)
    color/alpha 信息以数组形式存在,并存储于 ImageData 对象的 data 属性中。
       
  2. 得到像素数据 getImageData(sx, sy, sw, sh)
    sx:将要被提取的图像数据矩形区域的左上角X坐标。
    sy:将要被提取的图像数据矩形区域的左上角y坐标。
    sw:将要被提取的图像数据矩形区域的宽度。
    sh:将要被提取的图像数据矩形区域的高度。
  3. 创建ImageData对象
    createImageData(width,height)
        以指定的尺寸(以像素计)创建新的 ImageData 对象,一个新的具体特定尺寸的ImageData对像。所有像素被预设为透明黑。
    createImageData(imageData);
        创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)。
  4. 写入像素数据
    putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
    imgData :规定要放回画布的 ImageData 对象。
    x :ImageData 对象左上角的 x 坐标,以像素计。
    y :ImageData 对象左上角的 y 坐标,以像素计。
    dirtyX :可选。水平值(x),以像素计,在画布上放置图像的位置。
    dirtyY :可选。垂直值(y),以像素计,在画布上放置图像的位置。
    dirtyWidth :可选。在画布上绘制图像所使用的宽度。
    dirtyHeight :可选。在画布上绘制图像所使用的高度。
    5.实例- 颜色反转
//图片对象
var img =  new Image();
img.src = "../img/Aulac10622_square.jpg"
img.onload = function(){
	draw();
	}
function draw(){
	ctx.drawImage(img,0,0);
	var imgData=ctx.getImageData(0,0,200,200);
	var data=imgData.data;
	for(var i=0;i<data.length;i+=4){
			data[i]=255-data[i];
			data[i+1]=255-data[i+1];
			data[i+2]=255-data[i+2];
			data[i+3]=255;
			}
    ctx.putImageData(imgData,200,200);
}

在这里插入图片描述

合成 & 裁剪

       绘制图形时,不同的图形会因为绘制的先后而有了层级关系(多个图层)。如果新绘制的图形和原有内容有重叠部分,在默认情况下,新绘制的图形是会覆盖在原有内容之上。
       在HTML中可以添加z-index来修改层级关系,在canvas里可以利用globalCompositeOperation 属性来改变。

ctx.globalCompositeOperation ="source-over"
source-over(默认值) 新图形会覆盖在原有内容之上
source-in新图形仅仅会出现与原有内容重叠的部分,其他区域都变成透明的
source-out只有新图形中与原有内容不重叠的部分会被绘制出来
source-atop新图形中与原有内容重叠部分会被绘制,并覆盖于原有内容之上
lighter两图形中重叠部分作加色处理
xor重叠部分会变成透明
destination-over会在原有内容之上绘制新图形
destination-in原有内容与新图形重叠的部分会被保留,其他部分变成透明的
destination-out原有内容中与新图形不重叠的部分会被保留
destination-atop原有内容中与新图形重叠部分会被保留,并会在原有内容之上绘制新图形
darker两图形重叠部分作减色处理
copy只有新图形会被保留,其他都被清除掉

在这里插入图片描述

生成图片&保存

       在canvas中绘出的图片只是canvas标签而已,并非是真正的图片,我们并不能保存,不过我们可以利用canvas.toDataURL()这个方法把canvas绘制的图形生成一幅图片,生成图片后,就能对图片进行相应的操作了。

       首先我们定义用一个a标签定义下载的链接,然后再给a设置下载的链接。

<a id="download"  download="aa.png">下载</a>
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
//图片对象
var img =  new Image();
img.src = "../img/Aulac10622_square.jpg"
img.onload = function(){
		draw();
		}
function draw(){
		ctx.drawImage(img,0,0);
		var imgData=ctx.getImageData(0,0,200,200);
		var data=imgData.data;
		for(var i=0;i<data.length;i+=4){
		data[i]=255-data[i];
		data[i+1]=255-data[i+1];
		data[i+2]=255-data[i+2];
		data[i+3]=255;
}
ctx.putImageData(imgData,200,200);
//截图保存颜色反转画布
var imageURL=canvas.toDataURL("image/jpeg")
document.getElementById("download").href=imageURL
	}		
}	

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值