@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.
Files changed (4) hide show
  1. package/LICENSE +7 -7
  2. package/README.md +24 -24
  3. package/dist/bundle.js +322 -195
  4. 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
- [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](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
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](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.4
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 = "6";
26
+ this.context.lineWidth = 2;
27
27
 
28
28
  if (useLegacy) {
29
29
  this.commentYOffset = 0.25;
30
30
  } else {
31
- this.commentYOffset = 0.125;
31
+ this.commentYOffset = 0.2;
32
32
  }
33
33
 
34
- this.commentYMarginTop = 10;
34
+ this.commentYMarginTop = 0.08;
35
35
  this.fontSize = {
36
36
  "small": {
37
- "default": 45,
38
- "resized": 18
37
+ "default": 47,
38
+ "resized": 27.5
39
39
  },
40
40
  "medium": {
41
- "default": 85,
42
- "resized": 35
41
+ "default": 76,
42
+ "resized": 39
43
43
  },
44
44
  "big": {
45
- "default": 120,
46
- "resized": 57.5
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.parseCommand(comment);
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
- while (is_change && count < 10) {
233
- is_change = false;
234
- count++;
235
-
236
- for (let j = 0; j < 500; j++) {
237
- let vpos = comment.vpos + j;
238
- let left_pos = 1920 - (1920 + comment.width_max) * j / 500;
239
-
240
- if (left_pos + comment.width_max >= 1880) {
241
- for (let k in this.collision_right[vpos]) {
242
- let l = this.collision_right[vpos][k];
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
- if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
245
- if (data[l].posY + data[l].height > posY) {
246
- posY = data[l].posY + data[l].height;
247
- is_change = true;
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
- if (posY + comment.height > 1080) {
251
- if (1080 < comment.height) {
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
- if (is_break) {
264
- break;
289
+ if (is_break) {
290
+ break;
291
+ }
265
292
  }
266
- }
267
293
 
268
- if (left_pos <= 40 && is_break === false) {
269
- for (let k in this.collision_left[vpos]) {
270
- let l = this.collision_left[vpos][k];
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 > 1080) {
279
- if (1080 < comment.height) {
280
- posY = 0;
281
- } else {
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
- is_break = true;
286
- break;
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 < 300; 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 === "shita") {
492
- for (let i in lines) {
493
- let line = lines[i];
494
- let posY = 1080 - comment.posY + i * (comment.fontSize + this.commentYMarginTop) - comment.height + this.commentYOffset * comment.fontSize;
495
- this.context.strokeText(line, posX, posY);
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,0,1)";
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
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
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
- parseCommand(comment) {
535
- let metadata = comment.mail,
536
- loc = "naka",
537
- size = "medium",
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
- let length = false;
552
+ this.context.strokeText(line, posX, posY);
553
+ this.context.fillText(line, posX, posY);
552
554
 
553
- for (let i in metadata) {
554
- let match = metadata[i].match(/@([0-9]+)/);
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 (match) {
557
- length = match[1];
558
- break;
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
- this.nicoScripts.reverse.push({
567
- "start": comment.vpos,
568
- "end": comment.vpos + length * 100,
569
- "target": reverse[1]
570
- });
571
- fontSize = 0;
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 === "naka") {
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 === "medium") {
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 === "#ffffff") {
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 === 'defont') {
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
- * @param vpos - 動画の現在位置の100倍 ニコニコから吐き出されるコメントの位置情報は主にこれ
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
- for (let index in this.timeline[vpos]) {
751
- let comment = this.data[this.timeline[vpos][index]];
752
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
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
- if (comment._live) {
755
- let rgb = hex2rgb(comment.color);
756
- this.context.fillStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},0.5)`;
757
- } else {
758
- this.context.fillStyle = comment.color;
759
- }
874
+ if (comment.invisible) {
875
+ continue;
876
+ }
760
877
 
761
- if (comment.color === "#000000") {
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
- this.drawText(comment, vpos);
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
- if (comment.color === "#000000") {
768
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
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",
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
+ }