UNPKG

10.7 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[![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
13Danmaku 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
21You can install it with npm:
22
23```bash
24npm install danmaku
25```
26
27```js
28// Full version
29import Danmaku from 'danmaku';
30// DOM engine only
31import Danmaku from 'danmaku/dist/esm/danmaku.dom.js';
32// Canvas engine only
33import Danmaku from 'danmaku/dist/esm/danmaku.canvas.js';
34```
35
36Or 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
74To 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
76Here is a simple example using with Socket.IO and Node.js.
77
78Server:
79
80```js
81const app = require('http').createServer(handler);
82const io = require('socket.io')(app);
83app.listen(80);
84function handler(req, res) {
85 // your handler...
86}
87io.on('connection', socket => {
88 socket.on('danmaku', comment => {
89 socket.broadcast.emit('danmaku', comment);
90 });
91});
92```
93
94Client:
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
130var 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
155danmaku.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
215More details about [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D).
216
217Tips:
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
226Do it when you resize container.
227
228```js
229danmaku.resize();
230```
231
232### Show
233
234```js
235danmaku.show();
236```
237
238### Hide
239
240If 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
243danmaku.hide();
244```
245
246### Clear
247
248Clear current stage.
249
250```js
251danmaku.clear();
252```
253
254### Speed
255
256There 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
259danmaku.speed = 144;
260```
261
262### Destroy
263
264Destroy `danmaku` instance and release memory.
265
266```js
267danmaku.destroy();
268```