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