-
Notifications
You must be signed in to change notification settings - Fork 22
/
api.zh.html
355 lines (333 loc) · 14.4 KB
/
api.zh.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<title>弹幕建议接口规范</title>
<meta charset='utf-8'>
<link rel="stylesheet" href="./local.css" />
<script src='https://www.w3.org/Tools/respec/respec-w3c' async class='remove'></script>
<script class='remove'>
var respecConfig = {
specStatus: "CG-DRAFT",
edDraftURI: "https://w3c.github.io/danmaku/api.zh.html",
shortName: "danmaku",
editors: [{
name: "黄之昊",
companyURL: "https://www.bilibili.com/",
company: "哔哩哔哩"
}, {
name: "徐嵩",
companyURL: 'http://www.migu.cn',
company: "中国移动咪咕"
},{
name: "薛富侨",
companyURL: "http://www.chinaw3c.org/",
company: "W3C"
}, {
name: "赵磊",
companyURL: "http://www.migu.cn",
company: "中国移动咪咕"
}, {
name: "谭兆歆",
companyURL: "https://www.bilibili.com/",
company: "哔哩哔哩"
}, {
name: "陈亚军",
companyURL: 'http://www.migu.cn',
company: "中国移动咪咕"
}],
wg: "Bullet Chatting Community Group",
wgURI: "https://www.w3.org/community/bullet-chatting/",
github: {
repoURL: "https://github.com/w3c/danmaku",
branch: "main"
},
};
</script>
</head>
<body>
<section id='abstract'>
<p>
此文档描述了当前开发者实现弹幕的方式,并且提出一个新的 Web 接口以在浏览器中更轻便地实现弹幕功能。
</p>
</section>
<section id='sotd'>
<p>
这是一份进行中的提案草稿。欢迎参加 <a href="https://www.w3.org/community/bullet-chatting/">W3C 弹幕社区组</a>关于弹幕的相关讨论。
</p>
</section>
<section id="terminology">
<h2>术语</h2>
<p>
本文档使用了如下术语:
</p>
<ul>
<li>
<dfn>Canvas</dfn> — 用于在网页中绘制图形或者动画。[[2dcontext]]
</li>
<li>
<dfn>WebVTT</dfn> — 一种用于标记文本轨道的文件格式。[[webvtt1]]
</li>
</ul>
</section>
<section>
<h2>当前弹幕实现方式</h2>
<p>当前开发者实现弹幕主要有如下两种方式:</p>
<ul>
<li>Canvas 动态绘制弹幕</li>
<li>CSS 动态绘制弹幕</li>
</ul>
<section>
<h2>Canvas 动态绘制弹幕</h2>
<section>
<h2>元素</h2>
<div>每个弹幕都是一个 Canvas 渲染上下文。如:</div>
<aside class="example" title="弹幕元素">
<pre>
const ctx = canvas.getContext('2d');
ctx.fillText('bulletchat', x, y); // 其中x表示横方向的坐标,y表示纵方向的坐标
</pre>
</aside>
</section>
<section>
<h2>样式</h2>
<div>通过给弹幕赋予 Canvas 属性:字体(font)、颜色(fillStyle)、透明度(globalAlpha)等实现样式。如:</div>
<aside class="example" title="弹幕样式设置">
<pre>
ctx.font = '20px Arial';
ctx.fillStyle = '#000000';
</pre>
</aside>
</section>
<section>
<h2>运动</h2>
<div>每一帧都需要对所有弹幕进行重绘。每次改变之前需要先使用<code>clearRect</code>方法清空画布、计算弹幕在下一帧的位置、在新位置绘制弹幕。如:</div>
<aside class="example" title="弹幕刷新">
<pre>
const text = 'bulletchat'
const bulletList = [{
text,
color: '#ccc',
left: canvas.offsetWidth, // 用于标识弹幕x轴坐标
top: getRandomTop(), // 用于标识弹幕y轴坐标
offset: getBulletOffset(), // 弹幕移动速度,由canvas实际宽度和移动时间来算出
width: Math.ceil(ctx.measureText(text).width) // 文字像素宽度
}]
function drawBullets() {
for(let index = 0, l = bulletList.length; index < l; i++) {
let bullet = bulletList[index];
let {left, width, top, offset, color, text} = bullet
// 检测弹幕是否超出屏幕
if (left + width <= 0 ) {
bulletList.splice(index, 1);
index--;
continue;
}
// 不停修改弹幕x轴坐标
bullet.left -= bullet.offset
ctx.fillStyle = color;
ctx.fillText(text, left, top);
}
requestAnimationFrame(drawBullets);
}
</pre>
</aside>
</section>
</section>
<section>
<h2>CSS 动态绘制弹幕</h2>
<section>
<h2>元素</h2>
<div>每个弹幕都是一个 div 元素,即 <code><div>danmaku</div></code></div>
</section>
<section>
<h2>样式</h2>
<div>通过给弹幕赋予 CSS 样式:字号(font-size)、颜色(color)、透明度(opacity)等实现样式。</div>
</section>
<section>
<h2>运动</h2>
<div>滚动及逆向滚动弹幕有水平方向的运动。以滚动弹幕(从右往左滚动方向)为例:</div>
<div>运行:弹幕初始状态定位在最右侧,在 <code>transform</code> 和 <code>transition</code> 两个 CSS 属性的作用下向左运动。如:</div>
<aside class="example" title="">
<pre>
position: absolute;
top: 0;
left: 980px;
transform: translateX(0) translateY(0) translateZ(0);
transition: transform 5s linear;
</pre>
</aside>
<div>暂停:把弹幕元素的 <code>transform</code> 属性设为当前位置,同时把 <code>transition</code> 属性时间设为 0,就实现了把弹幕固定在当前位置。如:</div>
<aside class="example" title="">
<pre>
transform: translateX(-980px) translateY(0) translateZ(0);
transition: transform 0s linear;
</pre>
</aside>
</section>
</section>
<section>
<h2>现有弹幕实现方式优缺点分析</h2>
<section>
<h2>Canvas 方式</h2>
<section>
<h2>优点</h2>
<p>
性能较好,配合WebGL可以提升应用性能,同时可以同时显示大量的弹幕文字。
</p>
</section>
<section>
<h2>缺点</h2>
<p>
不够灵活,显示文字+图像的弹幕比较麻烦;对单独某条弹幕进行暂停比较繁琐。同时在移动设备上需要考虑Canvas分辨率的问题,比如文字发虚等。
</p>
</section>
</section>
<section>
<h2>CSS 方式</h2>
<section>
<h2>优点</h2>
<p>
简单灵活,可以通过DOM绘制丰富的弹幕样式,比如图像和文字的组合。用户可以单独暂停某一个感兴趣的弹幕。
</p>
</section>
<section>
<h2>缺点</h2>
<p>
弹幕较多时会生成的大量的DOM,消耗更多的内存,容易导致页面卡顿。同时需要对弹幕展示进行特定的优化,比如在弹幕消失,需要删除对应的DOM。
</p>
</section>
</section>
</section>
</section>
<section id='proposal'>
<h2>建议接口与属性</h2>
<p class="note">
本章的内容仍在<a href="https://www.w3.org/2011/webtv/">媒体和娱乐兴趣组</a>讨论,如果您有任何问题或内容更正,您可以<a href="https://github.com/w3c/danmaku/issues">在本文档的 GitHub 库中发一个新 issue</a> 或发送电子邮件至 <a href="mailto:[email protected]">[email protected]</a>。
</p>
<section>
<h2>样例</h2>
<aside class="example" title="弹幕使用">
<pre>
<bulletchatlist area="100" >
<bulletchat mode="scroll" >这里是弹幕内容</bulletchat>
<bulletchat mode="bottom" >固定在底部弹幕</bulletchat>
</bulletchatlist>
</pre>
</aside>
<figure>
<img alt="示例示意图" src="images/sample1.png" width="600">
<figcaption>
图为两条滚动弹幕和一条底部弹幕
</figcaption>
</figure>
<p class="note">
弹幕采用全新的标签元素<code>bulletchatlist</code>和<code>bulletchat</code>,新增的弹幕标签元素不是<code>video</code>或者<code>audio</code>等元素的子元素。从“<a
href="usecase.zh.html#scenarios">使用场景</a>”可以看到,弹幕不仅只是和视频等媒体元素有关联,在“<a href="usecase.zh.html#web">Web页面</a>”或者“<a
href="usecase.zh.html#generatedID-11">互动上墙</a>”等场景下弹幕是独立作为页面的一部分存在,不依赖于视频等元素。
</p>
<p class="note">
弹幕规范描述了弹幕绘制方式,不包括外部列表。由于弹幕不依赖于<code>video</code>,因此不要求有弹幕列表。在常见的点播视频弹幕场景中,往往有一个类似[[webvtt1]]这样同步视频时间轴的弹幕列表,
这种情况需要由开发者根据视频时间添加<code>bulletchat</code>。
</p>
</section>
<section>
<h2>元素</h2>
<p><code>bulletchatlist</code> 为块元素,<code>bulletchat</code> 为行内元素。<code>bulletchat</code> 元素允许嵌套内容内容包括:文本、图片、超链接。</p>
</section>
<section>
<h2>属性</h2>
<section>
<h2>bulletchatlist 元素</h2>
<ul>
<li><code>area</code>:定义弹幕显示区域占 bulletchatlist 总高度的百分比,范围 0-100,50为半屏,100为满屏。滚动弹幕、顶部弹幕、逆向滚动显示区域从 bulletchatlist 顶部开始计算,底部弹幕显示区域从 bulletchatlist 底部开始计算。</li>
<li>
<code>allowOverlap</code>:定义超出显示区域的弹幕是否允许重叠。<code>false</code>表示不展示超出显示区域弹幕,<code>true</code>则表示超出显示区域弹幕会进行重叠展示。
</li>
</ul>
<figure>
<img alt="area示例示意图" src="images/sample4.png" width="600">
<figcaption>
图为 area = 70 时,滚动弹幕只在 0 - 70% 高度的蓝色区域显示
</figcaption>
</figure>
<figure>
<img alt="allowOverlap示例示意图" src="images/sample3.png" width="600">
<figcaption>
图为 allowOverlap = true; area = 70,弹幕显示区域显示不下时,显示不下的弹幕(使用绿色标识)重叠在正常弹幕上方
</figcaption>
</figure>
</section>
<section>
<h2>bulletchat 元素</h2>
<ul>
<li>
<code>mode</code>:定义弹幕类型,可选值为<code>scroll</code>、<code>top</code>、<code>bottom</code>以及<code>reverse</code>。
<p><code>scroll</code> 为默认值,表示滚动弹幕。弹幕会从左往右进行滚动,滚动时间由CSS
属性<code>bulletchat-duration</code>控制。显示时间规则为:<code>bulletchat</code>元素的最左侧进入<code>bulletchatlist</code>元素显示区域到
<code>bulletchat</code>元素最右侧从<code>bulletchatlist</code>元素显示区域消失所消耗的时间。</p>
<figure>
<img alt="scroll示例示意图" src="images/sample5.png" width="600">
<figcaption>
图为两条滚动弹幕正在从右往左滚动
</figcaption>
</figure>
<p><code>top</code> 表示顶部弹幕。</p>
<figure>
<img alt="top示例示意图" src="images/sample6.png" width="600">
<figcaption>
图为两条顶部弹幕
</figcaption>
</figure>
<p><code>bottom</code> 表示底部弹幕。</p>
<figure>
<img alt="bottom示例示意图" src="images/sample7.png" width="600">
<figcaption>
图为两条底部弹幕
</figcaption>
</figure>
<p><code>reverse</code> 表示逆向滚动弹幕。弹幕会从右往左进行滚动,滚动时间与<code>scroll</code>类似。</p>
<figure>
<img alt="reverse示例示意图" src="images/sample8.png" width="600">
<figcaption>
图为三条逆向弹幕正在从左往右滚动
</figcaption>
</figure>
</li>
</ul>
</section>
</section>
<section>
<h2>事件</h2>
<section>
<h2>bulletchat 元素</h2>
<ul>
<li><code>bulletchatstart</code>:弹幕动画开始时触发。</li>
<li><code>bulletchatend</code>:弹幕动画结束时触发。</li>
<li><code>bulletchatcancel</code>:弹幕意外终止时触发,如弹幕被移除或被隐藏,或因为超出显示区域不被展示。</li>
</ul>
</section>
</section>
<section>
<h2>样式</h2>
<section>
<h2>bulletchatlist 元素</h2>
<ul>
<li><code>bulletchat-play-state</code>:running | paused,定义弹幕状态为运行或暂停,可继承。</li>
<li><code>bulletchat-duration</code>:<time>,单位为秒(s)或者毫秒(ms),定义弹幕播放速度,可继承。</li>
<li>字号、颜色、边框、行高、透明度、阴影等,同现有 CSS 属性。</li>
</ul>
</section>
<section>
<h2>bulletchat 元素</h2>
<ul>
<li><code>bulletchat-play-state</code>:running | paused,定义弹幕状态为运行或者暂停,可继承。</li>
<li><code>bulletchat-duration</code>:<time>,单位为秒(s)或者毫秒(ms),定义弹幕播放速度,可继承。</li>
<li><code>bulletchat-delay</code>:<time>,单位为秒(s)或者毫秒(ms),定义弹幕动画于何时开始,定义一个负值可以实现一个弹幕从中间开始运动。
</li>
<li>字号、颜色、边框、行高、透明度、阴影等,同现有 CSS 属性。</li>
</ul>
</section>
</section>
</section>
</body>
</html>