关于HTML5那些事儿1

HTML5 是如何起步的?

HTML5 W3C WHATWG 合作的结果。

编者注:W3C World Wide Web Consortium,万维网联盟。

编者注:WHATWG Web Hypertext Application Technology Working Group

WHATWG 致力于 web 表单和应用程序,而 W3C 专注于 XHTML 2.0。在 2006 年,双方决定进行合作,来创建一个新版本的 HTML

新特性

HTML5 中的一些有趣的新特性:

· 用于绘画的 canvas 元素

· 用于媒介回放的 video audio 元素

· 对本地离线存储的更好的支持

· 新的特殊内容元素,比如 articlefooterheadernavsection

· 新的表单控件,比如 calendardatetimeemailurlsearch

浏览器支持

最新版本的 SafariChromeFirefox 以及 Opera 支持某些 HTML5 特性。Internet Explorer 9 将支持某些 HTML5 特性。

HTML 5 视频

HTML5 规定了一种通过 video 元素来包含视频的标准方法。

视频格式

当前,video 元素支持三种视频格式:

格式

IE

Firefox

Opera

Chrome

Safari

Ogg

No

3.5+

10.5+

5.0+

No

MPEG 4

9.0+

No

No

5.0+

3.0+

WebM

No

4.0+

10.6+

6.0+

No

Ogg = 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件

MPEG4 = 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件

WebM = 带有 VP8 视频编码和 Vorbis 音频编码的 WebM 文件

<video src="movie.ogg" controls="controls">

</video>

control 属性供添加播放、暂停和音量控件。

包含宽度和高度属性也是不错的主意。

<video> </video> 之间插入的内容是供不支持 video 元素的浏览器显示的:

实例

<video src="movie.ogg" width="320" height="240" controls="controls">

Your browser does not support the video tag.

</video>

要确保适用于 Safari 浏览器,视频文件必须是 MPEG4 类型。

video 元素允许多个 source 元素。source 元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式:

实例

<video width="320" height="240" controls="controls">

  <source src="movie.ogg" type="video/ogg">

  <source src="movie.mp4" type="video/mp4">

Your browser does not support the video tag.

</video>

Internet Explorer

Internet Explorer 8 不支持 video 元素。在 IE 9 中,将提供对使用 MPEG4 video 元素的支持。

<video> 标签的属性

属性

描述

autoplay

autoplay

如果出现该属性,则视频在就绪后马上播放。

controls

controls

如果出现该属性,则向用户显示控件,比如播放按钮。

height

pixels

设置视频播放器的高度。

loop

loop

如果出现该属性,则当媒介文件完成播放后再次开始播放。

preload

preload

如果出现该属性,则视频在页面加载时进行加载,并预备播放。

如果使用 "autoplay",则忽略该属性。

src

url

要播放的视频的 URL。

width

pixels

设置视频播放器的宽度。

HTML5 <video> - 使用 DOM 进行控制

HTML5 <video> 元素同样拥有方法、属性和事件。

HTML5 <video> - 方法、属性以及事件

下面列出了大多数浏览器支持的视频方法、属性和事件:

方法

属性

事件

play()

currentSrc

play

pause()

currentTime

pause

load()

videoWidth

progress

canPlayType

videoHeight

error

 

duration

timeupdate

 

ended

ended

 

error

abort

 

paused

empty

 

muted

emptied

 

seeking

waiting

 

volume

loadedmetadata

 

height

 

 

width

 

注释:在所有属性中,只有 videoWidth videoHeight 属性是立即可用的。在视频的元数据已加载后,其他属性才可用。

HTML5 提供了播放音频的标准。

HTML5 规定了一种通过 audio 元素来包含音频的标准方法。

audio 元素能够播放声音文件或者音频流。

音频格式

当前,audio 元素支持三种音频格式:

 

IE 9

Firefox 3.5

Opera 10.5

Chrome 3.0

Safari 3.0

Ogg Vorbis

 

 

MP3

 

 

Wav

 

 

如何工作

如需在 HTML5 中播放音频,您所有需要的是:

<audio src="song.ogg" controls="controls">

</audio>

control 属性供添加播放、暂停和音量控件。

<audio> </audio> 之间插入的内容是供不支持 audio 元素的浏览器显示的:

实例

<audio src="song.ogg" controls="controls">

Your browser does not support the audio tag.

</audio>

要确保适用于 Safari 浏览器,音频文件必须是 MP3 Wav 类型。

audio 元素允许多个 source 元素。source 元素可以链接不同的音频文件。浏览器将使用第一个可识别的格式:

实例

<audio controls="controls">

  <source src="song.ogg" type="audio/ogg">

  <source src="song.mp3" type="audio/mpeg">

Your browser does not support the audio tag.

</audio>

Internet Explorer

Internet Explorer 8 不支持 audio 元素。在 IE 9 中,将提供对 audio 元素的支持。

<audio> 标签的属性

属性

描述

autoplay

autoplay

如果出现该属性,则音频在就绪后马上播放。

controls

controls

如果出现该属性,则向用户显示控件,比如播放按钮。

loop

loop

如果出现该属性,则每当音频结束时重新开始播放。

preload

preload

如果出现该属性,则音频在页面加载时进行加载,并预备播放。

如果使用 "autoplay",则忽略该属性。

src

url

要播放的音频的 URL。

HTML 5 拖放

拖放(Drag 和 drop)是 HTML5 标准的组成部分。

HTML5 拖放实例

下面的例子是一个简单的拖放实例:

实例

<!DOCTYPE HTML>

<html>

<head>

<script type="text/javascript">

function allowDrop(ev)

{

ev.preventDefault();

}

 

function drag(ev)

{

ev.dataTransfer.setData("Text",ev.target.id);

}

 

function drop(ev)

{

ev.preventDefault();

var data=ev.dataTransfer.getData("Text");

ev.target.appendChild(document.getElementById(data));

}

</script>

</head>

<body>

 

<div id="div1" οndrοp="drop(event)"

οndragοver="allowDrop(event)"></div>

<img id="drag1" src="img_logo.gif" draggable="true"

οndragstart="drag(event)" width="336" height="69" />

 

</body>

</html>

设置元素为可拖放

首先,为了使元素可拖动,把 draggable 属性设置为 true

<img draggable="true" />

拖动什么 - ondragstart 和 setData()

然后,规定当元素被拖动时,会发生什么。

在上面的例子中,ondragstart 属性调用了一个函数,drag(event),它规定了被拖动的数据。

dataTransfer.setData() 方法设置被拖数据的数据类型和值:

function drag(ev)

{

ev.dataTransfer.setData("Text",ev.target.id);

}

在这个例子中,数据类型是 "Text",值是可拖动元素的 id ("drag1")

放到何处 - ondragover

ondragover 事件规定在何处放置被拖动的数据。

默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。

这要通过调用 ondragover 事件的 event.preventDefault() 方法:

event.preventDefault()

进行放置 - ondrop

当放置被拖数据时,会发生 drop 事件。

在上面的例子中,ondrop 属性调用了一个函数,drop(event)

function drop(ev)

{

ev.preventDefault();

var data=ev.dataTransfer.getData("Text");

ev.target.appendChild(document.getElementById(data));

}

代码解释:

· 调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)

· 通过 dataTransfer.getData("Text") 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。

· 被拖数据是被拖元素的 id ("drag1")

· 把被拖元素追加到放置元素(目标元素)中

HTML 5 Canvas

canvas 元素用于在网页上绘制图形。

画布是一个矩形区域,您可以控制其每一像素。

canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

创建 Canvas 元素

HTML5 页面添加 canvas 元素。

规定元素的 id、宽度和高度:

<canvas id="myCanvas" width="200" height="100"></canvas>

通过 JavaScript 来绘制

canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:

<script type="text/javascript">

var c=document.getElementById("myCanvas");

var cxt=c.getContext("2d");

cxt.fillStyle="#FF0000";

cxt.fillRect(0,0,150,75);

</script>

JavaScript 使用 id 来寻找 canvas 元素:

var c=document.getElementById("myCanvas");

然后,创建 context 对象:

var cxt=c.getContext("2d");

getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

下面的两行代码绘制一个红色的矩形:

cxt.fillStyle="#FF0000";

cxt.fillRect(0,0,150,75);

fillStyle 方法将其染成红色,fillRect 方法规定了形状、位置和尺寸。

理解坐标

上面的 fillRect 方法拥有参数 (0,0,150,75)

意思是:在画布上绘制 150x75 的矩形,从左上角开始 (0,0)

如下图所示,画布的 X Y 坐标用于在画布上对绘画进行定位。

实例 - 图像

把一幅图像放置到画布上:

JavaScript 代码:

<script type="text/javascript">

 

var c=document.getElementById("myCanvas");

var cxt=c.getContext("2d");

var img=new Image()

img.src="flower.png"

cxt.drawImage(img,0,0);

 

</script>

canvas 元素:

<canvas id="myCanvas" width="200" height="100" style="border:1px solid #c3c3c3;">

Your browser does not support the canvas element.

</canvas>

HTML5 内联 SVG

什么是SVG?

· SVG 指可伸缩矢量图形 (Scalable Vector Graphics)

· SVG 用于定义用于网络的基于矢量的图形

· SVG 使用 XML 格式定义图形

· SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失

· SVG 是万维网联盟的标准

SVG 的优势

与其他图像格式相比(比如 JPEG GIF),使用 SVG 的优势在于:

· SVG 图像可通过文本编辑器来创建和修改

· SVG 图像可被搜索、索引、脚本化或压缩

· SVG 是可伸缩的

· SVG 图像可在任何的分辨率下被高质量地打印

· SVG 可在图像质量不下降的情况下被放大

SVG 直接嵌入 HTML 页面

实例

<!DOCTYPE html>

<html>

<body>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190">

  <polygon points="100,10 40,180 190,60 10,60 160,180"

  style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" />

</svg>

</body>

</html>

 

HTML 5 Canvas vs. SVG

SVG

SVG 是一种使用 XML 描述 2D 图形的语言。

SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。

SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

Canvas

Canvas 通过 JavaScript 来绘制 2D 图形。

Canvas 是逐像素进行渲染的。

canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。

Canvas 与 SVG 的比较

Canvas

· 依赖分辨率

· 不支持事件处理器

· 弱的文本渲染能力

· 能够以 .png .jpg 格式保存结果图像

· 最适合图像密集型的游戏,其中的许多对象会被频繁重绘

SVG

· 不依赖分辨率

· 支持事件处理器

· 最适合带有大型渲染区域的应用程序(比如谷歌地图)

· 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)

· 不适合游戏应用

HTML5 地理定位

HTML5 - 使用地理定位

请使用 getCurrentPosition() 方法来获得用户的位置。

下例是一个简单的地理定位实例,可返回用户位置的经度和纬度。

实例

<script>

var x=document.getElementById("demo");

function getLocation()

  {

  if (navigator.geolocation)

    {

    navigator.geolocation.getCurrentPosition(showPosition);

    }

  else{x.innerHTML="Geolocation is not supported by this browser.";}

  }

function showPosition(position)

  {

  x.innerHTML="Latitude: " + position.coords.latitude +

  "<br />Longitude: " + position.coords.longitude;

  }

</script>

例子解释:

· 检测是否支持地理定位

· 如果支持,则运行 getCurrentPosition() 方法。如果不支持,则向用户显示一段消息。

· 如果getCurrentPosition()运行成功,则向参数showPosition中规定的函数返回一个coordinates对象

· showPosition() 函数获得并显示经度和纬度

上面的例子是一个非常基础的地理定位脚本,不含错误处理。

处理错误和拒绝

getCurrentPosition() 方法的第二个参数用于处理错误。它规定当获取用户位置失败时运行的函数:

实例

function showError(error)

  {

  switch(error.code)

    {

    case error.PERMISSION_DENIED:

      x.innerHTML="User denied the request for Geolocation."

      break;

    case error.POSITION_UNAVAILABLE:

      x.innerHTML="Location information is unavailable."

      break;

    case error.TIMEOUT:

      x.innerHTML="The request to get user location timed out."

      break;

    case error.UNKNOWN_ERROR:

      x.innerHTML="An unknown error occurred."

      break;

    }

  }

错误代码:

· Permission denied - 用户不允许地理定位

· Position unavailable - 无法获取当前位置

· Timeout - 操作超时

在地图中显示结果

如需在地图中显示结果,您需要访问可使用经纬度的地图服务,比如谷歌地图或百度地图:

实例

function showPosition(position)

{

var latlon=position.coords.latitude+","+position.coords.longitude;

 

var img_url="http://maps.googleapis.com/maps/api/staticmap?center="

+latlon+"&zoom=14&size=400x300&sensor=false";

 

document.getElementById("mapholder").innerHTML="<img src='"+img_url+"' />";

}

getCurrentPosition() 方法 - 返回数据

若成功,则 getCurrentPosition() 方法返回对象。始终会返回 latitudelongitude 以及 accuracy 属性。如果可用,则会返回其他下面的属性。

属性

描述

coords.latitude

十进制数的纬度

coords.longitude

十进制数的经度

coords.accuracy

位置精度

coords.altitude

海拔,海平面以上以米计

coords.altitudeAccuracy

位置的海拔精度

coords.heading

方向,从正北开始以度计

coords.speed

速度,以米/每秒计

timestamp

响应的日期/时间

Geolocation 对象 - 其他有趣的方法

watchPosition() - 返回用户的当前位置,并继续返回用户移动时的更新位置(就像汽车上的 GPS)。

clearWatch() - 停止 watchPosition() 方法

下面的例子展示 watchPosition() 方法。您需要一台精确的 GPS 设备来测试该例(比如 iPhone):

实例

<script>

var x=document.getElementById("demo");

function getLocation()

  {

  if (navigator.geolocation)

    {

    navigator.geolocation.watchPosition(showPosition);

    }

  else{x.innerHTML="Geolocation is not supported by this browser.";}

  }

function showPosition(position)

  {

  x.innerHTML="Latitude: " + position.coords.latitude +

  "<br />Longitude: " + position.coords.longitude;

  }

</script>

HTML 5 Web 存储

HTML5 提供了两种在客户端存储数据的新方法:

· localStorage - 没有时间限制的数据存储

· sessionStorage - 针对一个 session 的数据存储

localStorage 方法

localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用。

如何创建和访问 localStorage

实例

<script type="text/javascript">localStorage.lastname="Smith";

document.write(localStorage.lastname);

</script>

下面的例子对用户访问页面的次数进行计数:

实例

<script type="text/javascript">

if (localStorage.pagecount)

  {

  localStorage.pagecount=Number(localStorage.pagecount) +1;

  }

else

  {

  localStorage.pagecount=1;

  }

document.write("Visits "+ localStorage.pagecount + " time(s).");

</script>

sessionStorage 方法

sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

如何创建并访问一个 sessionStorage

实例

<script type="text/javascript">sessionStorage.lastname="Smith";

document.write(sessionStorage.lastname);

</script>

下面的例子对用户在当前 session 中访问页面的次数进行计数:

实例

<script type="text/javascript">

if (sessionStorage.pagecount)

  {

  sessionStorage.pagecount=Number(sessionStorage.pagecount) +1;

  }

else

  {

  sessionStorage.pagecount=1;

  }

document.write("Visits "+sessionStorage.pagecount+" time(s) this session.");

</script>

HTML 5 应用程序缓存

使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本。

应用程序缓存为应用带来三个优势:

· 离线浏览 - 用户可在应用离线时使用它们

· 速度 - 已缓存资源加载得更快

· 减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。

HTML5 Cache Manifest 实例

下面的例子展示了带有 cache manifest HTML 文档(供离线浏览):

实例

<!DOCTYPE HTML>

<html manifest="demo.appcache">

 

<body>

The content of the document......

</body>

 

</html>

Cache Manifest 基础

如需启用应用程序缓存,请在文档的 <html> 标签中包含 manifest 属性:

<!DOCTYPE HTML>

<html manifest="demo.appcache">

...

</html>

每个指定了 manifest 的页面在用户对其访问时都会被缓存。如果未指定 manifest 属性,则页面不会被缓存(除非在 manifest 文件中直接指定了该页面)。

manifest 文件的建议的文件扩展名是:".appcache"

请注意,manifest 文件需要配置正确的 MIME-type,即 "text/cache-manifest"。必须在 web 服务器上进行配置。

Manifest 文件

manifest 文件是简单的文本文件,它告知浏览器被缓存的内容(以及不缓存的内容)。

manifest 文件可分为三个部分:

· CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存

· NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存

· FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

CACHE MANIFEST

第一行,CACHE MANIFEST,是必需的:

CACHE MANIFEST

/theme.css

/logo.gif

/main.js

上面的 manifest 文件列出了三个资源:一个 CSS 文件,一个 GIF 图像,以及一个 JavaScript 文件。当 manifest 文件加载后,浏览器会从网站的根目录下载这三个文件。然后,无论用户何时与因特网断开连接,这些资源依然是可用的。

NETWORK

下面的 NETWORK 小节规定文件 "login.asp" 永远不会被缓存,且离线时是不可用的:

NETWORK:

login.asp

可以使用星号来指示所有其他资源/文件都需要因特网连接:

NETWORK:

*

FALLBACK

下面的 FALLBACK 小节规定如果无法建立因特网连接,则用 "offline.html" 替代 /html5/ 目录中的所有文件:

FALLBACK:

/html5/ /404.html

注释:第一个 URI 是资源,第二个是替补。

更新缓存

一旦应用被缓存,它就会保持缓存直到发生下列情况:

· 用户清空浏览器缓存

· manifest 文件被修改(参阅下面的提示)

· 由程序来更新应用缓存

实例 - 完整的 Manifest 文件

CACHE MANIFEST

# 2012-02-21 v1.0.0

/theme.css

/logo.gif

/main.js

 

NETWORK:

login.asp

 

FALLBACK:

/html5/ /404.html

重要的提示:以 "#" 开头的是注释行,但也可满足其他用途。应用的缓存会在其 manifest 文件更改时被更新。如果您编辑了一幅图片,或者修改了一个 JavaScript 函数,这些改变都不会被重新缓存。更新注释行中的日期和版本号是一种使浏览器重新缓存文件的办法。

关于应用程序缓存的注释

请留心缓存的内容。

一旦文件被缓存,则浏览器会继续展示已缓存的版本,即使您修改了服务器上的文件。为了确保浏览器更新缓存,您需要更新 manifest 文件。

注释:浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。

HTML 5 Web Workers

web worker 是运行在后台的 JavaScript,不会影响页面的性能。

检测 Web Worker 支持

在创建 web worker 之前,请检测用户的浏览器是否支持它:

if(typeof(Worker)!=="undefined")

  {

  // Yes! Web worker support!

  // Some code.....

  }

else

  {

  // Sorry! No Web Worker support..

  }

创建 web worker 文件

在这里,我们创建了计数脚本。该脚本存储于 "demo_workers.js" 文件中:

var i=0;

 

function timedCount()

{

i=i+1;postMessage(i);

setTimeout("timedCount()",500);

}

 

timedCount();

以上代码中重要的部分是 postMessage() 方法 - 它用于向 HTML 页面传回一段消息。

注释:web worker 通常不用于如此简单的脚本,而是用于更耗费 CPU 资源的任务。

创建 Web Worker 对象

我们已经有了 web worker 文件,现在我们需要从 HTML 页面调用它。

下面的代码检测是否存在 worker,如果不存在,- 它会创建一个新的 web worker 对象,然后运行 "demo_workers.js" 中的代码:

if(typeof(w)=="undefined")

  {

  w=new Worker("demo_workers.js");

  }

然后我们就可以从 web worker 发生和接收消息了。

web worker 添加一个 "onmessage" 事件监听器:

w.onmessage=function(event){

document.getElementById("result").innerHTML=event.data;

};

web worker 传递消息时,会执行事件监听器中的代码。event.data 中存有来自 event.data 的数据。

终止 Web Worker

当我们创建 web worker 对象后,它会继续监听消息(即使在外部脚本完成之后)直到其被终止为止。

如需终止 web worker,并释放浏览器/计算机资源,请使用 terminate() 方法:

w.terminate();

完整的 Web Worker 实例代码

我们已经看到了 .js 文件中的 Worker 代码。下面是 HTML 页面的代码:

实例

<!DOCTYPE html>

<html>

<body>

 

<p>Count numbers: <output id="result"></output></p>

<button οnclick="startWorker()">Start Worker</button>

<button οnclick="stopWorker()">Stop Worker</button>

<br /><br />

 

<script>

var w;

 

function startWorker()

{

if(typeof(Worker)!=="undefined")

{

  if(typeof(w)=="undefined")

    {

    w=new Worker("demo_workers.js");

    }

  w.onmessage = function (event) {

    document.getElementById("result").innerHTML=event.data;

  };

}

else

{

document.getElementById("result").innerHTML="Sorry, your browser

 does not support Web Workers...";

}

}

 

function stopWorker()

{

w.terminate();

}

</script>

 

</body>

</html>

HTML 5 服务器发送事件

HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新。

Server-Sent 事件 - 单向消息传递

接收 Server-Sent 事件通知

EventSource 对象用于接收服务器发送事件通知:

实例

var source=new EventSource("demo_sse.php");

source.onmessage=function(event)

  {

  document.getElementById("result").innerHTML+=event.data + "<br />";

  };

服务器端代码实例

为了让上面的例子可以运行,您还需要能够发送数据更新的服务器(比如 PHP ASP)。

服务器端事件流的语法是非常简单的。把 "Content-Type" 报头设置为 "text/event-stream"。现在,您可以开始发送事件流了。

PHP 代码 (demo_sse.php):

<?php

header('Content-Type: text/event-stream');

header('Cache-Control: no-cache');

 

$time = date('r');

echo "data: The server time is: {$time}\n\n";

flush();

?>

ASP 代码 (VB) (demo_sse.asp):

<%

Response.ContentType="text/event-stream"

Response.Expires=-1

Response.Write("data: " & now())

Response.Flush()

%>

代码解释:

· 把报头 "Content-Type" 设置为 "text/event-stream"

· 规定不对页面进行缓存

· 输出发送日期(始终以 "data: " 开头)

· 向网页刷新输出数据

EventSource 对象

在上面的例子中,我们使用 onmessage 事件来获取消息。不过还可以使用其他事件:

事件

描述

onopen

当通往服务器的连接被打开

onmessage

当接收到消息

onerror

当错误发生


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值