@xpadev-net/niconicomments 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -7
- package/README.md +24 -24
- package/dist/bundle.js +322 -195
- package/package.json +33 -33
package/LICENSE
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Copyright (c) 2021 xpadev https://xpadev.net
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
-
|
|
5
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
-
|
|
7
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
Copyright (c) 2021 xpadev https://xpadev.net
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
# [niconicomments](https://xpadev.net/niconicomments/)
|
|
2
|
-
[](https://github.com/xpadev-net/niconicomments/blob/master/LICENSE)
|
|
3
|
-
ニコニコ動画の公式プレイヤーに多少の互換性を持つコメント描画ライブラリです
|
|
4
|
-
This is a comment drawing library that is somewhat compatible with the official Nico Nico Douga player.
|
|
5
|
-
Reference: https://xpadev.net/niconicomments/docs/
|
|
6
|
-
Github: https://github.com/xpadev-net/niconicomments
|
|
7
|
-
|
|
8
|
-
## Installation
|
|
9
|
-
```html
|
|
10
|
-
<script src="https://cdn.jsdelivr.net/npm/@xpadev-net/niconicomments@latest/dist/bundle.min.js"></script>
|
|
11
|
-
```
|
|
12
|
-
or
|
|
13
|
-
```
|
|
14
|
-
npm i @xpadev-net/niconicomments
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Examples
|
|
18
|
-
```javascript
|
|
19
|
-
const niconiComments = new NiconiComments(canvas, comments);
|
|
20
|
-
niconiComments.drawCanvas(vpos)
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Sample
|
|
24
|
-
https://xpadev.net/niconicomments/sample.html
|
|
1
|
+
# [niconicomments](https://xpadev.net/niconicomments/)
|
|
2
|
+
[](https://github.com/xpadev-net/niconicomments/blob/master/LICENSE)
|
|
3
|
+
ニコニコ動画の公式プレイヤーに多少の互換性を持つコメント描画ライブラリです
|
|
4
|
+
This is a comment drawing library that is somewhat compatible with the official Nico Nico Douga player.
|
|
5
|
+
Reference: https://xpadev.net/niconicomments/docs/
|
|
6
|
+
Github: https://github.com/xpadev-net/niconicomments
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
```html
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/@xpadev-net/niconicomments@latest/dist/bundle.min.js"></script>
|
|
11
|
+
```
|
|
12
|
+
or
|
|
13
|
+
```
|
|
14
|
+
npm i @xpadev-net/niconicomments
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
```javascript
|
|
19
|
+
const niconiComments = new NiconiComments(canvas, comments);
|
|
20
|
+
niconiComments.drawCanvas(vpos)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Sample
|
|
24
|
+
https://xpadev.net/niconicomments/sample.html
|
package/dist/bundle.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
niconicomments.js v0.1.
|
|
2
|
+
niconicomments.js v0.1.5
|
|
3
3
|
(c) 2021 xpadev-net https://xpadevn.et
|
|
4
4
|
Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
})(this, (function () { 'use strict';
|
|
11
11
|
|
|
12
12
|
class NiconiComments {
|
|
13
|
-
/**
|
|
14
|
-
* NiconiComments Constructor
|
|
15
|
-
* @param {HTMLCanvasElement} canvas - 描画対象のキャンバス
|
|
16
|
-
* @param {[]} data - 描画用のコメント
|
|
17
|
-
* @param {boolean} useLegacy - defontにsans-serifを適用するか(trueでニコニコ公式に準拠)
|
|
18
|
-
* @param {boolean} formatted - dataが独自フォーマットに変換されているか
|
|
13
|
+
/**
|
|
14
|
+
* NiconiComments Constructor
|
|
15
|
+
* @param {HTMLCanvasElement} canvas - 描画対象のキャンバス
|
|
16
|
+
* @param {[]} data - 描画用のコメント
|
|
17
|
+
* @param {boolean} useLegacy - defontにsans-serifを適用するか(trueでニコニコ公式に準拠)
|
|
18
|
+
* @param {boolean} formatted - dataが独自フォーマットに変換されているか
|
|
19
19
|
*/
|
|
20
20
|
constructor(canvas, data, useLegacy = false, formatted = false) {
|
|
21
21
|
this.canvas = canvas;
|
|
@@ -23,29 +23,40 @@
|
|
|
23
23
|
this.context.strokeStyle = "rgba(0,0,0,0.7)";
|
|
24
24
|
this.context.textAlign = "left";
|
|
25
25
|
this.context.textBaseline = "top";
|
|
26
|
-
this.context.lineWidth =
|
|
26
|
+
this.context.lineWidth = 2;
|
|
27
27
|
|
|
28
28
|
if (useLegacy) {
|
|
29
29
|
this.commentYOffset = 0.25;
|
|
30
30
|
} else {
|
|
31
|
-
this.commentYOffset = 0.
|
|
31
|
+
this.commentYOffset = 0.2;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
this.commentYMarginTop =
|
|
34
|
+
this.commentYMarginTop = 0.08;
|
|
35
35
|
this.fontSize = {
|
|
36
36
|
"small": {
|
|
37
|
-
"default":
|
|
38
|
-
"resized":
|
|
37
|
+
"default": 47,
|
|
38
|
+
"resized": 27.5
|
|
39
39
|
},
|
|
40
40
|
"medium": {
|
|
41
|
-
"default":
|
|
42
|
-
"resized":
|
|
41
|
+
"default": 76,
|
|
42
|
+
"resized": 39
|
|
43
43
|
},
|
|
44
44
|
"big": {
|
|
45
|
-
"default":
|
|
46
|
-
"resized":
|
|
45
|
+
"default": 118,
|
|
46
|
+
"resized": 62.5
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
+
this.defaultCommandValue = {
|
|
50
|
+
loc: "naka",
|
|
51
|
+
size: "medium",
|
|
52
|
+
fontSize: this.fontSize.medium.default,
|
|
53
|
+
color: "#ffffff",
|
|
54
|
+
font: 'defont',
|
|
55
|
+
full: false,
|
|
56
|
+
ender: false,
|
|
57
|
+
_live: false,
|
|
58
|
+
invisible: false
|
|
59
|
+
};
|
|
49
60
|
this.doubleResizeMaxWidth = {
|
|
50
61
|
full: {
|
|
51
62
|
legacy: 3020,
|
|
@@ -68,7 +79,8 @@
|
|
|
68
79
|
this.showCommentCount = false;
|
|
69
80
|
this.timeline = {};
|
|
70
81
|
this.nicoScripts = {
|
|
71
|
-
"reverse": []
|
|
82
|
+
"reverse": [],
|
|
83
|
+
"default": []
|
|
72
84
|
};
|
|
73
85
|
this.collision_right = {};
|
|
74
86
|
this.collision_left = {};
|
|
@@ -83,10 +95,10 @@
|
|
|
83
95
|
this.fpsCount = 0;
|
|
84
96
|
}, 500);
|
|
85
97
|
}
|
|
86
|
-
/**
|
|
87
|
-
* ニコニコが吐き出したデータを処理しやすいように変換する
|
|
88
|
-
* @param {[]} data - ニコニコが吐き出したコメントデータ
|
|
89
|
-
* @returns {*[]} - 独自フォーマットのコメントデータ
|
|
98
|
+
/**
|
|
99
|
+
* ニコニコが吐き出したデータを処理しやすいように変換する
|
|
100
|
+
* @param {[]} data - ニコニコが吐き出したコメントデータ
|
|
101
|
+
* @returns {*[]} - 独自フォーマットのコメントデータ
|
|
90
102
|
*/
|
|
91
103
|
|
|
92
104
|
|
|
@@ -130,8 +142,8 @@
|
|
|
130
142
|
});
|
|
131
143
|
return data_;
|
|
132
144
|
}
|
|
133
|
-
/**
|
|
134
|
-
* 事前に当たり判定を考慮してコメントの描画場所を決定する
|
|
145
|
+
/**
|
|
146
|
+
* 事前に当たり判定を考慮してコメントの描画場所を決定する
|
|
135
147
|
*/
|
|
136
148
|
|
|
137
149
|
|
|
@@ -140,15 +152,15 @@
|
|
|
140
152
|
this.getCommentSize();
|
|
141
153
|
this.getCommentPos();
|
|
142
154
|
}
|
|
143
|
-
/**
|
|
144
|
-
* コマンドをもとに各コメントに適用するフォントを決定する
|
|
155
|
+
/**
|
|
156
|
+
* コマンドをもとに各コメントに適用するフォントを決定する
|
|
145
157
|
*/
|
|
146
158
|
|
|
147
159
|
|
|
148
160
|
getFont() {
|
|
149
161
|
for (let i in this.data) {
|
|
150
162
|
let comment = this.data[i];
|
|
151
|
-
let command = this.
|
|
163
|
+
let command = this.parseCommandAndNicoscript(comment);
|
|
152
164
|
this.data[i].loc = command.loc;
|
|
153
165
|
this.data[i].size = command.size;
|
|
154
166
|
this.data[i].fontSize = command.fontSize;
|
|
@@ -157,11 +169,13 @@
|
|
|
157
169
|
this.data[i].full = command.full;
|
|
158
170
|
this.data[i].ender = command.ender;
|
|
159
171
|
this.data[i]._live = command._live;
|
|
172
|
+
this.data[i].long = command.long;
|
|
173
|
+
this.data[i].invisible = command.invisible;
|
|
160
174
|
this.data[i].content = this.data[i].content.replaceAll("\t", " ");
|
|
161
175
|
}
|
|
162
176
|
}
|
|
163
|
-
/**
|
|
164
|
-
* コメントの描画サイズを計算する
|
|
177
|
+
/**
|
|
178
|
+
* コメントの描画サイズを計算する
|
|
165
179
|
*/
|
|
166
180
|
|
|
167
181
|
|
|
@@ -174,6 +188,11 @@
|
|
|
174
188
|
|
|
175
189
|
for (let k in tmpData[i][j]) {
|
|
176
190
|
let comment = tmpData[i][j][k];
|
|
191
|
+
|
|
192
|
+
if (comment.invisible) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
|
|
177
196
|
let measure = this.measureText(comment);
|
|
178
197
|
this.data[comment.index].height = measure.height;
|
|
179
198
|
this.data[comment.index].width = measure.width;
|
|
@@ -188,8 +207,8 @@
|
|
|
188
207
|
}
|
|
189
208
|
}
|
|
190
209
|
}
|
|
191
|
-
/**
|
|
192
|
-
* 計算された描画サイズをもとに各コメントの配置位置を決定する
|
|
210
|
+
/**
|
|
211
|
+
* 計算された描画サイズをもとに各コメントの配置位置を決定する
|
|
193
212
|
*/
|
|
194
213
|
|
|
195
214
|
|
|
@@ -199,6 +218,10 @@
|
|
|
199
218
|
for (let i in data) {
|
|
200
219
|
let comment = data[i];
|
|
201
220
|
|
|
221
|
+
if (comment.invisible) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
202
225
|
for (let j = 0; j < 500; j++) {
|
|
203
226
|
if (!this.timeline[comment.vpos + j]) {
|
|
204
227
|
this.timeline[comment.vpos + j] = [];
|
|
@@ -229,73 +252,77 @@
|
|
|
229
252
|
is_change = true,
|
|
230
253
|
count = 0;
|
|
231
254
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
255
|
+
if (1080 < comment.height) {
|
|
256
|
+
posY = (comment.height - 1080) / -2;
|
|
257
|
+
} else {
|
|
258
|
+
while (is_change && count < 10) {
|
|
259
|
+
is_change = false;
|
|
260
|
+
count++;
|
|
261
|
+
|
|
262
|
+
for (let j = 0; j < 500; j++) {
|
|
263
|
+
let vpos = comment.vpos + j;
|
|
264
|
+
let left_pos = 1920 - (1920 + comment.width_max) * j / 500;
|
|
265
|
+
|
|
266
|
+
if (left_pos + comment.width_max >= 1880) {
|
|
267
|
+
for (let k in this.collision_right[vpos]) {
|
|
268
|
+
let l = this.collision_right[vpos][k];
|
|
269
|
+
|
|
270
|
+
if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
|
|
271
|
+
if (data[l].posY + data[l].height > posY) {
|
|
272
|
+
posY = data[l].posY + data[l].height;
|
|
273
|
+
is_change = true;
|
|
274
|
+
}
|
|
243
275
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
276
|
+
if (posY + comment.height > 1080) {
|
|
277
|
+
if (1080 < comment.height) {
|
|
278
|
+
posY = (comment.height - 1080) / -2;
|
|
279
|
+
} else {
|
|
280
|
+
posY = Math.floor(Math.random() * (1080 - comment.height));
|
|
281
|
+
}
|
|
249
282
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
posY = (comment.height - 1080) / -2;
|
|
253
|
-
} else {
|
|
254
|
-
posY = Math.floor(Math.random() * (1080 - comment.height));
|
|
283
|
+
is_break = true;
|
|
284
|
+
break;
|
|
255
285
|
}
|
|
256
|
-
|
|
257
|
-
is_break = true;
|
|
258
|
-
break;
|
|
259
286
|
}
|
|
260
287
|
}
|
|
261
|
-
}
|
|
262
288
|
|
|
263
|
-
|
|
264
|
-
|
|
289
|
+
if (is_break) {
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
265
292
|
}
|
|
266
|
-
}
|
|
267
293
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
|
|
273
|
-
if (data[l].posY + data[l].height > posY) {
|
|
274
|
-
posY = data[l].posY + data[l].height;
|
|
275
|
-
is_change = true;
|
|
276
|
-
}
|
|
294
|
+
if (left_pos <= 40 && is_break === false) {
|
|
295
|
+
for (let k in this.collision_left[vpos]) {
|
|
296
|
+
let l = this.collision_left[vpos][k];
|
|
277
297
|
|
|
278
|
-
if (posY + comment.height >
|
|
279
|
-
if (
|
|
280
|
-
posY =
|
|
281
|
-
|
|
282
|
-
posY = Math.random() * (1080 - comment.height);
|
|
298
|
+
if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
|
|
299
|
+
if (data[l].posY + data[l].height > posY) {
|
|
300
|
+
posY = data[l].posY + data[l].height;
|
|
301
|
+
is_change = true;
|
|
283
302
|
}
|
|
284
303
|
|
|
285
|
-
|
|
286
|
-
|
|
304
|
+
if (posY + comment.height > 1080) {
|
|
305
|
+
if (1080 < comment.height) {
|
|
306
|
+
posY = 0;
|
|
307
|
+
} else {
|
|
308
|
+
posY = Math.random() * (1080 - comment.height);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
is_break = true;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
287
314
|
}
|
|
288
315
|
}
|
|
316
|
+
|
|
317
|
+
if (is_break) {
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
289
320
|
}
|
|
290
321
|
|
|
291
322
|
if (is_break) {
|
|
292
323
|
break;
|
|
293
324
|
}
|
|
294
325
|
}
|
|
295
|
-
|
|
296
|
-
if (is_break) {
|
|
297
|
-
break;
|
|
298
|
-
}
|
|
299
326
|
}
|
|
300
327
|
}
|
|
301
328
|
|
|
@@ -362,7 +389,7 @@
|
|
|
362
389
|
}
|
|
363
390
|
}
|
|
364
391
|
|
|
365
|
-
for (let j = 0; j <
|
|
392
|
+
for (let j = 0; j < comment.long; j++) {
|
|
366
393
|
let vpos = comment.vpos + j;
|
|
367
394
|
arrayPush(this.timeline, vpos, i);
|
|
368
395
|
|
|
@@ -377,11 +404,11 @@
|
|
|
377
404
|
}
|
|
378
405
|
}
|
|
379
406
|
}
|
|
380
|
-
/**
|
|
381
|
-
* context.measureTextの複数行対応版
|
|
382
|
-
* 画面外にはみ出すコメントの縮小も行う
|
|
383
|
-
* @param comment - 独自フォーマットのコメントデータ
|
|
384
|
-
* @returns {{resized: boolean, width: number, width_max: number, fontSize: number, width_min: number, height: number}} - 描画サイズとリサイズの情報
|
|
407
|
+
/**
|
|
408
|
+
* context.measureTextの複数行対応版
|
|
409
|
+
* 画面外にはみ出すコメントの縮小も行う
|
|
410
|
+
* @param comment - 独自フォーマットのコメントデータ
|
|
411
|
+
* @returns {{resized: boolean, width: number, width_max: number, fontSize: number, width_min: number, height: number}} - 描画サイズとリサイズの情報
|
|
385
412
|
*/
|
|
386
413
|
|
|
387
414
|
|
|
@@ -420,7 +447,7 @@
|
|
|
420
447
|
width = width_arr.reduce((p, c) => p + c, 0) / width_arr.length;
|
|
421
448
|
width_max = Math.max(...width_arr);
|
|
422
449
|
width_min = Math.min(...width_arr);
|
|
423
|
-
height = (comment.fontSize + this.commentYMarginTop) * lines.length;
|
|
450
|
+
height = (comment.fontSize + this.commentYMarginTop * comment.fontSize) * lines.length;
|
|
424
451
|
|
|
425
452
|
if (comment.loc !== "naka" && !comment.tateRisized) {
|
|
426
453
|
if (comment.full && width_max > 1920) {
|
|
@@ -463,10 +490,10 @@
|
|
|
463
490
|
"fontSize": comment.fontSize
|
|
464
491
|
};
|
|
465
492
|
}
|
|
466
|
-
/**
|
|
467
|
-
* コマンドをもとに所定の位置にコメントを表示する
|
|
468
|
-
* @param comment - 独自フォーマットのコメントデータ
|
|
469
|
-
* @param {number} vpos - 動画の現在位置の100倍 ニコニコから吐き出されるコメントの位置情報は主にこれ
|
|
493
|
+
/**
|
|
494
|
+
* コマンドをもとに所定の位置にコメントを表示する
|
|
495
|
+
* @param comment - 独自フォーマットのコメントデータ
|
|
496
|
+
* @param {number} vpos - 動画の現在位置の100倍 ニコニコから吐き出されるコメントの位置情報は主にこれ
|
|
470
497
|
*/
|
|
471
498
|
|
|
472
499
|
|
|
@@ -488,32 +515,16 @@
|
|
|
488
515
|
let lines = comment.content.split("\n"),
|
|
489
516
|
posX = (1920 - comment.width_max) / 2;
|
|
490
517
|
|
|
491
|
-
if (comment.loc === "
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
this.context.fillText(line, posX, posY);
|
|
497
|
-
}
|
|
498
|
-
} else {
|
|
499
|
-
if (comment.loc === "naka") {
|
|
500
|
-
if (reverse) {
|
|
501
|
-
posX = (1920 + comment.width_max) * (vpos - comment.vpos) / 500 - comment.width_max;
|
|
502
|
-
} else {
|
|
503
|
-
posX = 1920 - (1920 + comment.width_max) * (vpos - comment.vpos) / 500;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
for (let i in lines) {
|
|
508
|
-
let line = lines[i];
|
|
509
|
-
let posY = comment.posY + i * (comment.fontSize + this.commentYMarginTop) + this.commentYOffset * comment.fontSize;
|
|
510
|
-
this.context.strokeText(line, posX, posY);
|
|
511
|
-
this.context.fillText(line, posX, posY);
|
|
518
|
+
if (comment.loc === "naka") {
|
|
519
|
+
if (reverse) {
|
|
520
|
+
posX = (1920 + comment.width_max) * (vpos - comment.vpos) / 500 - comment.width_max;
|
|
521
|
+
} else {
|
|
522
|
+
posX = 1920 - (1920 + comment.width_max) * (vpos - comment.vpos) / 500;
|
|
512
523
|
}
|
|
513
524
|
}
|
|
514
525
|
|
|
515
526
|
if (this.showCollision) {
|
|
516
|
-
this.context.strokeStyle = "rgba(255,255,
|
|
527
|
+
this.context.strokeStyle = "rgba(0,255,255,1)";
|
|
517
528
|
|
|
518
529
|
if (comment.loc === "shita") {
|
|
519
530
|
this.context.strokeRect(posX, 1080 - comment.posY - comment.height, comment.width_max, comment.height);
|
|
@@ -521,60 +532,67 @@
|
|
|
521
532
|
this.context.strokeRect(posX, comment.posY, comment.width_max, comment.height);
|
|
522
533
|
}
|
|
523
534
|
|
|
524
|
-
|
|
535
|
+
if (comment.color === "#000000") {
|
|
536
|
+
this.context.strokeStyle = "rgba(255,255,255,0.7)";
|
|
537
|
+
} else {
|
|
538
|
+
this.context.strokeStyle = "rgba(0,0,0,0.7)";
|
|
539
|
+
}
|
|
525
540
|
}
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* コメントに含まれるコマンドを解釈する
|
|
529
|
-
* @param comment- 独自フォーマットのコメントデータ
|
|
530
|
-
* @returns {{loc: string, size: string, color: string, fontSize: number, ender: boolean, font: string, full: boolean, _live: boolean}}
|
|
531
|
-
*/
|
|
532
541
|
|
|
542
|
+
for (let i in lines) {
|
|
543
|
+
let line = lines[i],
|
|
544
|
+
posY;
|
|
533
545
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
fontSize = this.fontSize.medium.default,
|
|
539
|
-
color = "#ffffff",
|
|
540
|
-
font = 'defont',
|
|
541
|
-
full = false,
|
|
542
|
-
ender = false,
|
|
543
|
-
reverse = comment.content.match(/@逆 ?(全|コメ|投コメ)?/),
|
|
544
|
-
_live = false;
|
|
545
|
-
|
|
546
|
-
if (reverse) {
|
|
547
|
-
if (!reverse[1]) {
|
|
548
|
-
reverse[1] = "全";
|
|
546
|
+
if (comment.loc === "shita") {
|
|
547
|
+
posY = 1080 - comment.posY + i * (comment.fontSize + this.commentYMarginTop * comment.fontSize) - comment.height + this.commentYOffset * comment.fontSize;
|
|
548
|
+
} else {
|
|
549
|
+
posY = comment.posY + i * (comment.fontSize + this.commentYMarginTop * comment.fontSize) + this.commentYOffset * comment.fontSize;
|
|
549
550
|
}
|
|
550
551
|
|
|
551
|
-
|
|
552
|
+
this.context.strokeText(line, posX, posY);
|
|
553
|
+
this.context.fillText(line, posX, posY);
|
|
552
554
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
+
if (this.showCollision) {
|
|
556
|
+
this.context.strokeStyle = "rgba(255,255,0,0.5)";
|
|
557
|
+
this.context.strokeRect(posX, posY, comment.width_max, comment.fontSize);
|
|
555
558
|
|
|
556
|
-
if (
|
|
557
|
-
|
|
558
|
-
|
|
559
|
+
if (comment.color === "#000000") {
|
|
560
|
+
this.context.strokeStyle = "rgba(255,255,255,0.7)";
|
|
561
|
+
} else {
|
|
562
|
+
this.context.strokeStyle = "rgba(0,0,0,0.7)";
|
|
559
563
|
}
|
|
560
564
|
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* コメントに含まれるコマンドを解釈する
|
|
569
|
+
* @param comment- 独自フォーマットのコメントデータ
|
|
570
|
+
* @returns {{loc: string|null, size: string|null, color: string|null, fontSize: number|null, ender: boolean, font: string|null, full: boolean, _live: boolean, invisible: boolean, long:number|null}}
|
|
571
|
+
*/
|
|
561
572
|
|
|
562
|
-
if (!length) {
|
|
563
|
-
length = 30;
|
|
564
|
-
}
|
|
565
573
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
574
|
+
parseCommand(comment) {
|
|
575
|
+
let metadata = comment.mail,
|
|
576
|
+
loc = null,
|
|
577
|
+
size = null,
|
|
578
|
+
fontSize = null,
|
|
579
|
+
color = null,
|
|
580
|
+
font = null,
|
|
581
|
+
full = false,
|
|
582
|
+
ender = false,
|
|
583
|
+
_live = false,
|
|
584
|
+
invisible = false,
|
|
585
|
+
long = null;
|
|
573
586
|
|
|
574
587
|
for (let i in metadata) {
|
|
575
588
|
let command = metadata[i].toLowerCase();
|
|
589
|
+
const match = command.match(/^@([0-9.]+)/);
|
|
590
|
+
|
|
591
|
+
if (match) {
|
|
592
|
+
long = match[1];
|
|
593
|
+
}
|
|
576
594
|
|
|
577
|
-
if (loc ===
|
|
595
|
+
if (loc === null) {
|
|
578
596
|
switch (command) {
|
|
579
597
|
case "ue":
|
|
580
598
|
loc = "ue";
|
|
@@ -586,7 +604,7 @@
|
|
|
586
604
|
}
|
|
587
605
|
}
|
|
588
606
|
|
|
589
|
-
if (size ===
|
|
607
|
+
if (size === null) {
|
|
590
608
|
switch (command) {
|
|
591
609
|
case "big":
|
|
592
610
|
size = "big";
|
|
@@ -600,7 +618,7 @@
|
|
|
600
618
|
}
|
|
601
619
|
}
|
|
602
620
|
|
|
603
|
-
if (color ===
|
|
621
|
+
if (color === null) {
|
|
604
622
|
switch (command) {
|
|
605
623
|
case "white":
|
|
606
624
|
color = "#FFFFFF";
|
|
@@ -700,7 +718,7 @@
|
|
|
700
718
|
}
|
|
701
719
|
}
|
|
702
720
|
|
|
703
|
-
if (font ===
|
|
721
|
+
if (font === null) {
|
|
704
722
|
switch (command) {
|
|
705
723
|
case "gothic":
|
|
706
724
|
font = "gothic";
|
|
@@ -723,6 +741,11 @@
|
|
|
723
741
|
|
|
724
742
|
case "_live":
|
|
725
743
|
_live = true;
|
|
744
|
+
break;
|
|
745
|
+
|
|
746
|
+
case "invisible":
|
|
747
|
+
invisible = true;
|
|
748
|
+
break;
|
|
726
749
|
}
|
|
727
750
|
}
|
|
728
751
|
|
|
@@ -734,12 +757,109 @@
|
|
|
734
757
|
font,
|
|
735
758
|
full,
|
|
736
759
|
ender,
|
|
737
|
-
_live
|
|
760
|
+
_live,
|
|
761
|
+
invisible,
|
|
762
|
+
long
|
|
738
763
|
};
|
|
739
764
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
765
|
+
|
|
766
|
+
parseCommandAndNicoscript(comment) {
|
|
767
|
+
let data = this.parseCommand(comment),
|
|
768
|
+
nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
|
|
769
|
+
|
|
770
|
+
if (nicoscript) {
|
|
771
|
+
switch (nicoscript[1]) {
|
|
772
|
+
case "デフォルト":
|
|
773
|
+
this.nicoScripts.default.push({
|
|
774
|
+
start: comment.vpos,
|
|
775
|
+
long: data.long === null ? null : Math.floor(data.long * 100),
|
|
776
|
+
color: data.color,
|
|
777
|
+
size: data.size,
|
|
778
|
+
font: data.font,
|
|
779
|
+
loc: data.loc
|
|
780
|
+
});
|
|
781
|
+
break;
|
|
782
|
+
|
|
783
|
+
case "逆":
|
|
784
|
+
let reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
|
|
785
|
+
|
|
786
|
+
if (!reverse[1]) {
|
|
787
|
+
reverse[1] = "全";
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (data.long === null) {
|
|
791
|
+
data.long = 30;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
this.nicoScripts.reverse.push({
|
|
795
|
+
"start": comment.vpos,
|
|
796
|
+
"end": comment.vpos + data.long * 100,
|
|
797
|
+
"target": reverse[1]
|
|
798
|
+
});
|
|
799
|
+
break;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
data.invisible = true;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
let color = "#FFFFFF",
|
|
806
|
+
size = "medium",
|
|
807
|
+
font = "defont",
|
|
808
|
+
loc = "naka";
|
|
809
|
+
|
|
810
|
+
for (let i in this.nicoScripts.default) {
|
|
811
|
+
if (this.nicoScripts.default[i].long !== null && this.nicoScripts.default[i].start + this.nicoScripts.default[i].long < comment.vpos) {
|
|
812
|
+
this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (this.nicoScripts.default[i].loc) {
|
|
817
|
+
loc = this.nicoScripts.default[i].loc;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (this.nicoScripts.default[i].color) {
|
|
821
|
+
color = this.nicoScripts.default[i].color;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (this.nicoScripts.default[i].size) {
|
|
825
|
+
size = this.nicoScripts.default[i].size;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
if (this.nicoScripts.default[i].font) {
|
|
829
|
+
font = this.nicoScripts.default[i].font;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
if (!data.loc) {
|
|
834
|
+
data.loc = loc;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (!data.color) {
|
|
838
|
+
data.color = color;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (!data.size) {
|
|
842
|
+
data.size = size;
|
|
843
|
+
data.fontSize = this.fontSize[data.size].default;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (!data.font) {
|
|
847
|
+
data.font = font;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
if (data.loc !== "naka") {
|
|
851
|
+
if (!data.long) {
|
|
852
|
+
data.long = 300;
|
|
853
|
+
} else {
|
|
854
|
+
data.long = Math.floor(data.long * 100);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
return data;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* キャンバスを描画する
|
|
862
|
+
* @param vpos - 動画の現在位置の100倍 ニコニコから吐き出されるコメントの位置情報は主にこれ
|
|
743
863
|
*/
|
|
744
864
|
|
|
745
865
|
|
|
@@ -747,25 +867,32 @@
|
|
|
747
867
|
this.fpsCount++;
|
|
748
868
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
749
869
|
|
|
750
|
-
|
|
751
|
-
let
|
|
752
|
-
|
|
870
|
+
if (this.timeline[vpos]) {
|
|
871
|
+
for (let index in this.timeline[vpos]) {
|
|
872
|
+
let comment = this.data[this.timeline[vpos][index]];
|
|
753
873
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
} else {
|
|
758
|
-
this.context.fillStyle = comment.color;
|
|
759
|
-
}
|
|
874
|
+
if (comment.invisible) {
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
760
877
|
|
|
761
|
-
|
|
762
|
-
this.context.strokeStyle = "rgba(255,255,255,0.7)";
|
|
763
|
-
}
|
|
878
|
+
this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
|
|
764
879
|
|
|
765
|
-
|
|
880
|
+
if (comment._live) {
|
|
881
|
+
let rgb = hex2rgb(comment.color);
|
|
882
|
+
this.context.fillStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},0.5)`;
|
|
883
|
+
} else {
|
|
884
|
+
this.context.fillStyle = comment.color;
|
|
885
|
+
}
|
|
766
886
|
|
|
767
|
-
|
|
768
|
-
|
|
887
|
+
if (comment.color === "#000000") {
|
|
888
|
+
this.context.strokeStyle = "rgba(255,255,255,0.7)";
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
this.drawText(comment, vpos);
|
|
892
|
+
|
|
893
|
+
if (comment.color === "#000000") {
|
|
894
|
+
this.context.strokeStyle = "rgba(0,0,0,0.7)";
|
|
895
|
+
}
|
|
769
896
|
}
|
|
770
897
|
}
|
|
771
898
|
|
|
@@ -783,8 +910,8 @@
|
|
|
783
910
|
this.context.fillText("Count:" + this.timeline[vpos].length, 100, 200);
|
|
784
911
|
}
|
|
785
912
|
}
|
|
786
|
-
/**
|
|
787
|
-
* キャンバスを消去する
|
|
913
|
+
/**
|
|
914
|
+
* キャンバスを消去する
|
|
788
915
|
*/
|
|
789
916
|
|
|
790
917
|
|
|
@@ -793,12 +920,12 @@
|
|
|
793
920
|
}
|
|
794
921
|
|
|
795
922
|
}
|
|
796
|
-
/**
|
|
797
|
-
* 配列を複数のキーでグループ化する
|
|
798
|
-
* @param {{}} array
|
|
799
|
-
* @param {string} key
|
|
800
|
-
* @param {string} key2
|
|
801
|
-
* @returns {{}}
|
|
923
|
+
/**
|
|
924
|
+
* 配列を複数のキーでグループ化する
|
|
925
|
+
* @param {{}} array
|
|
926
|
+
* @param {string} key
|
|
927
|
+
* @param {string} key2
|
|
928
|
+
* @returns {{}}
|
|
802
929
|
*/
|
|
803
930
|
|
|
804
931
|
|
|
@@ -820,12 +947,12 @@
|
|
|
820
947
|
|
|
821
948
|
return data;
|
|
822
949
|
};
|
|
823
|
-
/**
|
|
824
|
-
* フォント名とサイズをもとにcontextで使えるフォントを生成する
|
|
825
|
-
* @param {string} font
|
|
826
|
-
* @param {number} size
|
|
827
|
-
* @param {boolean} useLegacy
|
|
828
|
-
* @returns {string}
|
|
950
|
+
/**
|
|
951
|
+
* フォント名とサイズをもとにcontextで使えるフォントを生成する
|
|
952
|
+
* @param {string} font
|
|
953
|
+
* @param {number} size
|
|
954
|
+
* @param {boolean} useLegacy
|
|
955
|
+
* @returns {string}
|
|
829
956
|
*/
|
|
830
957
|
|
|
831
958
|
|
|
@@ -846,11 +973,11 @@
|
|
|
846
973
|
|
|
847
974
|
}
|
|
848
975
|
};
|
|
849
|
-
/**
|
|
850
|
-
* phpのarray_push的なあれ
|
|
851
|
-
* @param array
|
|
852
|
-
* @param {string} key
|
|
853
|
-
* @param push
|
|
976
|
+
/**
|
|
977
|
+
* phpのarray_push的なあれ
|
|
978
|
+
* @param array
|
|
979
|
+
* @param {string} key
|
|
980
|
+
* @param push
|
|
854
981
|
*/
|
|
855
982
|
|
|
856
983
|
|
|
@@ -865,10 +992,10 @@
|
|
|
865
992
|
|
|
866
993
|
array[key].push(push);
|
|
867
994
|
};
|
|
868
|
-
/**
|
|
869
|
-
* Hexからrgbに変換する(_live用)
|
|
870
|
-
* @param {string} hex
|
|
871
|
-
* @return {array} RGB
|
|
995
|
+
/**
|
|
996
|
+
* Hexからrgbに変換する(_live用)
|
|
997
|
+
* @param {string} hex
|
|
998
|
+
* @return {array} RGB
|
|
872
999
|
*/
|
|
873
1000
|
|
|
874
1001
|
|
package/package.json
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@xpadev-net/niconicomments",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "NiconiComments is a comment drawing library that is somewhat compatible with the official Nico Nico Douga player.",
|
|
5
|
-
"main": "dist/bundle.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
-
"build": "rollup -c rollup.config.js",
|
|
9
|
-
"prepublishOnly": "rollup -c rollup.config.js"
|
|
10
|
-
},
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/xpadev-net/niconicomments.git"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"niconico"
|
|
17
|
-
],
|
|
18
|
-
"author": "xpadev(xpadev.net)",
|
|
19
|
-
"bugs": {
|
|
20
|
-
"url": "https://github.com/xpadev-net/niconicomments/issues"
|
|
21
|
-
},
|
|
22
|
-
"files": [
|
|
23
|
-
"dist/bundle.js"
|
|
24
|
-
],
|
|
25
|
-
"homepage": "https://xpadev.net/niconicomments/docs/",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"rollup": "^2.61.1"
|
|
29
|
-
},
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"@rollup/plugin-babel": "^5.3.0"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@xpadev-net/niconicomments",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "NiconiComments is a comment drawing library that is somewhat compatible with the official Nico Nico Douga player.",
|
|
5
|
+
"main": "dist/bundle.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "rollup -c rollup.config.js",
|
|
9
|
+
"prepublishOnly": "rollup -c rollup.config.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/xpadev-net/niconicomments.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"niconico"
|
|
17
|
+
],
|
|
18
|
+
"author": "xpadev(xpadev.net)",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/xpadev-net/niconicomments/issues"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/bundle.js"
|
|
24
|
+
],
|
|
25
|
+
"homepage": "https://xpadev.net/niconicomments/docs/",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"rollup": "^2.61.1"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@rollup/plugin-babel": "^5.3.0"
|
|
32
|
+
}
|
|
33
|
+
}
|