UNPKG

10.6 kBMarkdownView Raw
1# Danmaku
2
3[![GitHub Action](https://github.com/weizhenye/Danmaku/workflows/CI/badge.svg)](https://github.com/weizhenye/Danmaku/actions)
4[![Coverage](https://badgen.net/codecov/c/github/weizhenye/Danmaku?icon=codecov)](https://codecov.io/gh/weizhenye/Danmaku)
5[![NPM version](https://badgen.net/npm/v/danmaku?icon=npm)](https://www.npmjs.com/package/danmaku)
6[![License](https://badgen.net/npm/license/danmaku?icon=https://api.iconify.design/octicon:law.svg?color=white)](https://github.com/weizhenye/Danmaku/blob/master/LICENSE)
7[![File size](https://badgen.net/bundlephobia/minzip/danmaku?icon=https://api.iconify.design/ant-design:file-zip-outline.svg?color=white)](https://bundlephobia.com/result?p=danmaku)
8[![jsDelivr](https://badgen.net/jsdelivr/hits/npm/danmaku?icon=https://api.iconify.design/simple-icons:jsdelivr.svg?color=white)](https://www.jsdelivr.com/package/npm/danmaku)
9
10[![Browser compatibility](https://saucelabs.com/browser-matrix/danmaku.svg)](https://saucelabs.com/u/danmaku)
11
12Danmaku is a JavaScript library to display flying comments on HTML media elements (video and audio). It can also display comments to your container in real time without timeline.
13
14[Demo](https://danmaku.js.org/)
15
16[中文文档](https://github.com/weizhenye/Danmaku/wiki/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3)
17
18## Installation
19
20You can install it with npm:
21
22```bash
23npm install danmaku
24```
25
26```js
27// Full version
28import Danmaku from 'danmaku';
29// DOM engine only
30import Danmaku from 'danmaku/dist/esm/danmaku.dom.js';
31// Canvas engine only
32import Danmaku from 'danmaku/dist/esm/danmaku.canvas.js';
33```
34
35Or use CDN ([jsDelivr](https://www.jsdelivr.com/package/npm/danmaku), [unpkg](https://unpkg.com/danmaku/)):
36
37| | Full | DOM engine only | Canvas engine only |
38| - | - | - | - |
39| UMD | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.js?label=danmaku.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.dom.js?label=danmaku.dom.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.dom.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.canvas.js?label=danmaku.canvas.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.canvas.js) |
40| UMD minified | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.min.js?label=danmaku.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.min.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.dom.min.js?label=danmaku.dom.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.dom.min.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/danmaku.canvas.min.js?label=danmaku.canvas.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/danmaku.canvas.min.js) |
41| ESM | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.js?label=esm/danmaku.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.dom.js?label=esm/danmaku.dom.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.dom.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.canvas.js?label=esm/danmaku.canvas.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.canvas.js) |
42| ESM minified | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.min.js?label=esm/danmaku.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.min.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.dom.min.js?label=esm/danmaku.dom.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.dom.min.js) | [![](https://badgen.net/badgesize/gzip/weizhenye/danmaku/master/dist/esm/danmaku.canvas.min.js?label=esm/danmaku.canvas.min.js)](https://cdn.jsdelivr.net/npm/danmaku/dist/esm/danmaku.canvas.min.js) |
43
44## Usage
45
46### Media mode
47
48```html
49<div id="my-video-container" style="width:640px;height:360px;position:relative;">
50 <video id="my-video" src="./example.mp4" style="position:absolute;"></video>
51</div>
52
53<div id="my-audio-container" style="width:640px;height:360px;position:relative;"></div>
54<audio id="my-audio" src="./example.mp3"></audio>
55
56<script src="path/to/danmaku.min.js"></script>
57<script>
58 var danmaku1 = new Danmaku({
59 container: document.getElementById('my-video-container'),
60 media: document.getElementById('my-video'),
61 comments: []
62 });
63 var danmaku2 = new Danmaku({
64 container: document.getElementById('my-audio-container'),
65 media: document.getElementById('my-audio'),
66 comments: []
67 });
68</script>
69```
70
71### Live mode
72
73To display comments in real time, you need to set up server and use something like [Socket.IO](http://socket.io/). Danmaku is just receiving comments data and display them to container.
74
75Here is a simple example using with Socket.IO and Node.js.
76
77Server:
78
79```js
80const app = require('http').createServer(handler);
81const io = require('socket.io')(app);
82app.listen(80);
83function handler(req, res) {
84 // your handler...
85}
86io.on('connection', socket => {
87 socket.on('danmaku', comment => {
88 socket.broadcast.emit('danmaku', comment);
89 });
90});
91```
92
93Client:
94
95```html
96<div id="my-container" style="width:640px;height:360px;"></div>
97<button id="send-button">Send</button>
98
99<script src="path/to/socket.io.js"></script>
100<script src="path/to/danmaku.min.js"></script>
101<script>
102 var danmaku = new Danmaku({
103 container: document.getElementById('my-container')
104 });
105 var socket = io();
106 socket.on('danmaku', function(comment) {
107 danmaku.emit(comment)
108 });
109 var btn = document.getElementById('send-button');
110 btn.addEventListener('click', function() {
111 var comment = {
112 text: 'bla bla',
113 style: {
114 fontSize: '20px',
115 color: '#ffffff'
116 },
117 };
118 danmaku.emit(comment);
119 socket.emit('danmaku', comment);
120 });
121</script>
122```
123
124## API
125
126### Initialization
127
128```js
129var danmaku = new Danmaku({
130 // REQUIRED. The stage to display comments will be appended to container.
131 container: document.getElementById('my-container'),
132
133 // media can be <video> or <audio> element,
134 // if it's not provided, Danmaku will be in live mode
135 media: document.getElementById('my-media'),
136
137 // Array of comment, used in media mode,
138 // you can find its format in `danmaku.emit` API.
139 comments: [],
140
141 // You can use DOM engine or canvas engine to render comments.
142 // Canvas engine may more efficient than DOM however it costs more memory.
143 // 'DOM' by default in full version.
144 engine: 'canvas',
145
146 // You can also set speed by using `danmaku.speed` API.
147 speed: 144
148});
149```
150
151### Emit a comment
152
153```js
154danmaku.emit({
155 text: 'example',
156
157 // 'rtl'(right to left) by default, available mode: 'ltr', 'rtl', 'top', 'bottom'.
158 mode: 'rtl',
159
160 // Specified in seconds, if not provided when using with media,
161 // it will be set to `media.currentTime`. Not required in live mode.
162 time: 233.3,
163
164 // When using DOM engine, Danmaku will create a <div> node for each comment,
165 // the style object will be set to `node.style` directly, just write with CSS rules.
166 // For example:
167 style: {
168 fontSize: '20px',
169 color: '#ffffff',
170 border: '1px solid #337ab7',
171 textShadow: '-1px -1px #000, -1px 1px #000, 1px -1px #000, 1px 1px #000'
172 },
173
174 // When using canvas engine, Danmaku will create a <canvas> object for each comment,
175 // you should pass in a CanvasRenderingContext2D object.
176 // For example:
177 style: {
178 font: '10px sans-serif',
179 textAlign: 'start',
180 // Note that 'bottom' is the default
181 textBaseline: 'bottom',
182 direction: 'inherit',
183 fillStyle: '#000',
184 strokeStyle: '#000',
185 lineWidth: 1.0,
186 // ...
187 },
188
189 // A custom render to draw comment.
190 // when `render` exist, `text` and `style` will be ignored.
191
192 // When using DOM engine, you should return an HTMLElement.
193 render: function() {
194 var $div = document.createElement('div');
195 var $img = document.createElement('img');
196 $img.src = '/path/to/xxx.png';
197 $div.appendChild($img);
198 return $div;
199 },
200 // When using canvas engine, you should return an HTMLCanvasElement.
201 render: function() {
202 var canvas = document.createElement('canvas');
203 canvas.width = 320;
204 canvas.height = 180;
205 var ctx = canvas.getContext('2d');
206 ctx.beginPath();
207 ctx.arc(75, 75, 50, 0, 2 * Math.PI);
208 ctx.stroke();
209 return canvas;
210 }
211});
212```
213
214More details about [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D).
215
216Tips:
217* With DOM engine, you may want to change line spacing by set `line-height` to each comment, a better way is set `line-height` to the container.
218* With canvas engine, line height is `1.2` by default, you can set it with `style.font`.
219* With canvas engine, `style.font` uses the same syntax as the [CSS font](https://developer.mozilla.org/en-US/docs/Web/CSS/font) specifier. However you can only use `px`, `%`, `em`, `rem` units, I'm sure you don't need others.
220* There is a hitbox for each comment, which height is determined by its line height. With canvas engine, when `style.textBaseline` is `top` or `hanging`, the baseline is set to top of the hitbox; when it's `middle`, baseline is middle of the hitbox; otherwise baseline is bottom of the hitbox. So if you set `style.textBaseline` to `alphabetic` or `hanging`, the comment's head or foot may out of the hitbox and be invisible.
221* With canvas engine, [`style.filter`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter) is supported in Chrome 52 and Firefox 49.
222
223### Resize
224
225Do it when you resize container.
226
227```js
228danmaku.resize();
229```
230
231### Show
232
233```js
234danmaku.show();
235```
236
237### Hide
238
239If you set `display: none;` to the container directly when using DOM engine, you should also do danmaku.hide() otherwise the typesetting will be broken when it's showed.
240
241```js
242danmaku.hide();
243```
244
245### Clear
246
247Clear current stage.
248
249```js
250danmaku.clear();
251```
252
253### Speed
254
255There is a property `duration` for all comments, which means how long will a comment be shown to the stage. `duration` is calculated by `stage.width / danmaku.speed`, and `danmaku.speed` is a standard for all comments, because the actually speed for each comment is then calculated by `(comment.width + stage.width) / duration`. The default value is 144.
256
257```js
258danmaku.speed = 144;
259```
260
261### Destroy
262
263Destroy `danmaku` instance and release memory.
264
265```js
266danmaku.destroy();
267```