@xpadev-net/niconicomments 0.2.4 → 0.2.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 +21 -21
  2. package/README.md +32 -32
  3. package/dist/bundle.js +881 -881
  4. package/package.json +37 -37
package/dist/bundle.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- niconicomments.js v0.2.4
2
+ niconicomments.js v0.2.5
3
3
  (c) 2021 xpadev-net https://xpadev.net
4
4
  Released under the MIT License.
5
5
  */
@@ -37,886 +37,886 @@
37
37
  return __assign.apply(this, arguments);
38
38
  };
39
39
 
40
- var NiconiComments = (function () {
41
- function NiconiComments(canvas, data, options) {
42
- if (options === void 0) { options = {
43
- useLegacy: false,
44
- formatted: false,
45
- video: null,
46
- showCollision: false,
47
- showFPS: false,
48
- showCommentCount: false,
49
- drawAllImageOnLoad: false
50
- }; }
51
- var _this = this;
52
- this.canvas = canvas;
53
- this.context = canvas.getContext("2d");
54
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
55
- this.context.textAlign = "start";
56
- this.context.textBaseline = "alphabetic";
57
- this.context.lineWidth = 4;
58
- this.commentYPaddingTop = 0.08;
59
- this.commentYMarginBottom = 0.24;
60
- this.fontSize = {
61
- "small": {
62
- "default": 47,
63
- "resized": 26.1
64
- },
65
- "medium": {
66
- "default": 74,
67
- "resized": 38.7
68
- },
69
- "big": {
70
- "default": 111,
71
- "resized": 61
72
- }
73
- };
74
- this.doubleResizeMaxWidth = {
75
- full: {
76
- legacy: 3020,
77
- "default": 3220
78
- },
79
- normal: {
80
- legacy: 2540,
81
- "default": 2740
82
- }
83
- };
84
- var parsedData = options.formatted ? data : this.parseData(data);
85
- this.video = options.video ? options.video : null;
86
- this.showCollision = options.showCollision;
87
- this.showFPS = options.showFPS;
88
- this.showCommentCount = options.showCommentCount;
89
- this.timeline = {};
90
- this.nicoScripts = { reverse: [], "default": [], replace: [], ban: [] };
91
- this.collision_right = {};
92
- this.collision_left = {};
93
- this.collision_ue = {};
94
- this.collision_shita = {};
95
- this.lastVpos = -1;
96
- this.useLegacy = options.useLegacy;
97
- this.preRendering(parsedData, options.drawAllImageOnLoad);
98
- this.fpsCount = 0;
99
- this.fps = 0;
100
- this.fpsClock = window.setInterval(function () {
101
- _this.fps = _this.fpsCount * 2;
102
- _this.fpsCount = 0;
103
- }, 500);
104
- }
105
- NiconiComments.prototype.parseData = function (data) {
106
- var data_ = [];
107
- for (var i = 0; i < data.length; i++) {
108
- for (var key in data[i]) {
109
- var value = data[i][key];
110
- if (key === "chat" && value["deleted"] !== 1) {
111
- var tmpParam = {
112
- "id": value["no"],
113
- "vpos": value["vpos"],
114
- "content": value["content"],
115
- "date": value["date"],
116
- "date_usec": value["date_usec"],
117
- "owner": !value["user_id"],
118
- "premium": value["premium"] === 1,
119
- "mail": []
120
- };
121
- if (value["mail"]) {
122
- tmpParam["mail"] = value["mail"].split(/[\s ]/g);
123
- }
124
- if (value["content"].startsWith("/") && !value["user_id"]) {
125
- tmpParam["mail"].push("invisible");
126
- }
127
- data_.push(tmpParam);
128
- }
129
- }
130
- }
131
- data_.sort(function (a, b) {
132
- if (a.vpos < b.vpos)
133
- return -1;
134
- if (a.vpos > b.vpos)
135
- return 1;
136
- if (a.date < b.date)
137
- return -1;
138
- if (a.date > b.date)
139
- return 1;
140
- if (a.date_usec < b.date_usec)
141
- return -1;
142
- if (a.date_usec > b.date_usec)
143
- return 1;
144
- return 0;
145
- });
146
- return data_;
147
- };
148
- NiconiComments.prototype.preRendering = function (rawData, drawAll) {
149
- var parsedData = this.getCommentPos(this.getCommentSize(this.getFont(rawData)));
150
- this.data = this.sortComment(parsedData);
151
- if (drawAll) {
152
- for (var i in parsedData) {
153
- this.getTextImage(Number(i));
154
- }
155
- }
156
- };
157
- NiconiComments.prototype.getFont = function (parsedData) {
158
- var result = [];
159
- for (var i in parsedData) {
160
- result[i] = this.parseCommandAndNicoscript(parsedData[i]);
161
- }
162
- return result;
163
- };
164
- NiconiComments.prototype.getCommentSize = function (parsedData) {
165
- var tmpData = groupBy(parsedData, "font", "fontSize");
166
- var result = [];
167
- for (var i in tmpData) {
168
- for (var j in tmpData[i]) {
169
- this.context.font = parseFont(i, j, this.useLegacy);
170
- for (var k in tmpData[i][j]) {
171
- var comment = tmpData[i][j][k];
172
- if (comment.invisible) {
173
- continue;
174
- }
175
- var measure = this.measureText(comment);
176
- result[comment.index] = parsedData[comment.index];
177
- result[comment.index].height = measure.height;
178
- result[comment.index].width = measure.width;
179
- result[comment.index].width_max = measure.width_max;
180
- result[comment.index].width_min = measure.width_min;
181
- if (measure.resized) {
182
- result[comment.index].fontSize = measure.fontSize;
183
- this.context.font = parseFont(i, j, this.useLegacy);
184
- }
185
- }
186
- }
187
- }
188
- return result;
189
- };
190
- NiconiComments.prototype.getCommentPos = function (parsedData) {
191
- var data = parsedData;
192
- for (var i in data) {
193
- var comment = data[i];
194
- if (comment.invisible) {
195
- continue;
196
- }
197
- for (var j = 0; j < 500; j++) {
198
- if (!this.timeline[comment.vpos + j]) {
199
- this.timeline[comment.vpos + j] = [];
200
- }
201
- if (!this.collision_right[comment.vpos + j]) {
202
- this.collision_right[comment.vpos + j] = [];
203
- }
204
- if (!this.collision_left[comment.vpos + j]) {
205
- this.collision_left[comment.vpos + j] = [];
206
- }
207
- if (!this.collision_ue[comment.vpos + j]) {
208
- this.collision_ue[comment.vpos + j] = [];
209
- }
210
- if (!this.collision_shita[comment.vpos + j]) {
211
- this.collision_shita[comment.vpos + j] = [];
212
- }
213
- }
214
- if (comment.loc === "naka") {
215
- comment.vpos -= 70;
216
- parsedData[i].vpos -= 70;
217
- var posY = 0, is_break = false, is_change = true, count = 0;
218
- if (1080 < comment.height) {
219
- posY = (comment.height - 1080) / -2;
220
- }
221
- else {
222
- while (is_change && count < 10) {
223
- is_change = false;
224
- count++;
225
- for (var j = 0; j < 500; j++) {
226
- var vpos = comment.vpos + j;
227
- var left_pos = 1920 - ((1920 + comment.width_max) * j / 500);
228
- if (left_pos + comment.width_max >= 1880) {
229
- for (var k in this.collision_right[vpos]) {
230
- var l = this.collision_right[vpos][k];
231
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
232
- if (data[l].posY + data[l].height > posY) {
233
- posY = data[l].posY + data[l].height;
234
- is_change = true;
235
- }
236
- if (posY + comment.height > 1080) {
237
- if (1080 < comment.height) {
238
- posY = (comment.height - 1080) / -2;
239
- }
240
- else {
241
- posY = Math.floor(Math.random() * (1080 - comment.height));
242
- }
243
- is_break = true;
244
- break;
245
- }
246
- }
247
- }
248
- if (is_break) {
249
- break;
250
- }
251
- }
252
- if (left_pos <= 40 && is_break === false) {
253
- for (var k in this.collision_left[vpos]) {
254
- var l = this.collision_left[vpos][k];
255
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
256
- if (data[l].posY + data[l].height > posY) {
257
- posY = data[l].posY + data[l].height;
258
- is_change = true;
259
- }
260
- if (posY + comment.height > 1080) {
261
- if (1080 < comment.height) {
262
- posY = 0;
263
- }
264
- else {
265
- posY = Math.random() * (1080 - comment.height);
266
- }
267
- is_break = true;
268
- break;
269
- }
270
- }
271
- }
272
- if (is_break) {
273
- break;
274
- }
275
- }
276
- if (is_break) {
277
- break;
278
- }
279
- }
280
- }
281
- }
282
- for (var j = 0; j < 500; j++) {
283
- var vpos = comment.vpos + j;
284
- var left_pos = 1920 - ((1920 + comment.width_max) * j / 500);
285
- arrayPush(this.timeline, vpos, i);
286
- if (left_pos + comment.width_max >= 1880) {
287
- arrayPush(this.collision_right, vpos, i);
288
- }
289
- if (left_pos <= 40) {
290
- arrayPush(this.collision_left, vpos, i);
291
- }
292
- }
293
- parsedData[i].posY = posY;
294
- }
295
- else {
296
- var posY = 0, is_break = false, is_change = true, count = 0, collision = void 0;
297
- if (comment.loc === "ue") {
298
- collision = this.collision_ue;
299
- }
300
- else if (comment.loc === "shita") {
301
- collision = this.collision_shita;
302
- }
303
- while (is_change && count < 10) {
304
- is_change = false;
305
- count++;
306
- for (var j = 0; j < 300; j++) {
307
- var vpos = comment.vpos + j;
308
- for (var k in collision[vpos]) {
309
- var l = collision[vpos][k];
310
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
311
- if (data[l].posY + data[l].height > posY) {
312
- posY = data[l].posY + data[l].height;
313
- is_change = true;
314
- }
315
- if (posY + comment.height > 1080) {
316
- if (1000 <= comment.height) {
317
- posY = 0;
318
- }
319
- else {
320
- posY = Math.floor(Math.random() * (1080 - comment.height));
321
- }
322
- is_break = true;
323
- break;
324
- }
325
- }
326
- }
327
- if (is_break) {
328
- break;
329
- }
330
- }
331
- }
332
- for (var j = 0; j < comment.long; j++) {
333
- var vpos = comment.vpos + j;
334
- arrayPush(this.timeline, vpos, i);
335
- if (comment.loc === "ue") {
336
- arrayPush(this.collision_ue, vpos, i);
337
- }
338
- else {
339
- arrayPush(this.collision_shita, vpos, i);
340
- }
341
- }
342
- parsedData[i].posY = posY;
343
- }
344
- }
345
- return parsedData;
346
- };
347
- NiconiComments.prototype.sortComment = function (parsedData) {
348
- for (var vpos in this.timeline) {
349
- this.timeline[vpos].sort(function (a, b) {
350
- var A = parsedData[a];
351
- var B = parsedData[b];
352
- if (!A.owner && B.owner) {
353
- return -1;
354
- }
355
- else if (A.owner && !B.owner) {
356
- return 1;
357
- }
358
- else {
359
- return 0;
360
- }
361
- });
362
- }
363
- return parsedData;
364
- };
365
- NiconiComments.prototype.measureText = function (comment) {
366
- var width, width_max, width_min, height, width_arr = [], lines = comment.content.split("\n");
367
- if (!comment.resized && !comment.ender) {
368
- if (comment.size === "big" && lines.length > 2) {
369
- comment.fontSize = this.fontSize.big.resized;
370
- comment.resized = true;
371
- comment.tateRisized = true;
372
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
373
- }
374
- else if (comment.size === "medium" && lines.length > 4) {
375
- comment.fontSize = this.fontSize.medium.resized;
376
- comment.resized = true;
377
- comment.tateRisized = true;
378
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
379
- }
380
- else if (comment.size === "small" && lines.length > 6) {
381
- comment.fontSize = this.fontSize.small.resized;
382
- comment.resized = true;
383
- comment.tateRisized = true;
384
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
385
- }
386
- }
387
- for (var i = 0; i < lines.length; i++) {
388
- var measure = this.context.measureText(lines[i]);
389
- width_arr.push(measure.width);
390
- }
391
- width = width_arr.reduce(function (p, c) { return p + c; }, 0) / width_arr.length;
392
- width_max = Math.max.apply(Math, width_arr);
393
- width_min = Math.min.apply(Math, width_arr);
394
- height = (comment.fontSize * (1 + this.commentYPaddingTop) * lines.length) + (this.commentYMarginBottom * comment.fontSize);
395
- if (comment.loc !== "naka" && !comment.tateRisized) {
396
- if (comment.full && width_max > 1840) {
397
- comment.fontSize -= 1;
398
- comment.resized = true;
399
- comment.yokoResized = true;
400
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
401
- return this.measureText(comment);
402
- }
403
- else if (!comment.full && width_max > 1440) {
404
- comment.fontSize -= 1;
405
- comment.resized = true;
406
- comment.yokoResized = true;
407
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
408
- return this.measureText(comment);
409
- }
410
- }
411
- else if (comment.loc !== "naka" && comment.tateRisized && (comment.full && width_max > 1920 || !comment.full && width_max > 1440) && !comment.yokoResized) {
412
- comment.fontSize = this.fontSize[comment.size]["default"];
413
- comment.resized = true;
414
- comment.yokoResized = true;
415
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
416
- return this.measureText(comment);
417
- }
418
- else if (comment.loc !== "naka" && comment.tateRisized && comment.yokoResized) {
419
- if (comment.full && width_max > this.doubleResizeMaxWidth.full[this.useLegacy ? "legacy" : "default"]) {
420
- comment.fontSize -= 1;
421
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
422
- return this.measureText(comment);
423
- }
424
- else if (!comment.full && width_max > this.doubleResizeMaxWidth.normal[this.useLegacy ? "legacy" : "default"]) {
425
- comment.fontSize -= 1.;
426
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
427
- return this.measureText(comment);
428
- }
429
- }
430
- return {
431
- "width": width,
432
- "width_max": width_max,
433
- "width_min": width_min,
434
- "height": height,
435
- "resized": comment.resized,
436
- "fontSize": comment.fontSize
437
- };
438
- };
439
- NiconiComments.prototype.drawText = function (comment, vpos) {
440
- var reverse = false;
441
- for (var i in this.nicoScripts.reverse) {
442
- var range = this.nicoScripts.reverse[i];
443
- if ((range.target === "コメ" && comment.owner) || (range.target === "投コメ" && !comment.owner)) {
444
- break;
445
- }
446
- if (range.start < vpos && vpos < range.end) {
447
- reverse = true;
448
- }
449
- }
450
- for (var i in this.nicoScripts.ban) {
451
- var range = this.nicoScripts.ban[i];
452
- if (range.start < vpos && vpos < range.end) {
453
- return;
454
- }
455
- }
456
- var posX = (1920 - comment.width_max) / 2, posY = comment.posY;
457
- if (comment.loc === "naka") {
458
- if (reverse) {
459
- posX = ((1920 + comment.width_max) * (vpos - comment.vpos) / 500) - comment.width_max;
460
- }
461
- else {
462
- posX = 1920 - ((1920 + comment.width_max) * (vpos - comment.vpos) / 500);
463
- }
464
- }
465
- else if (comment.loc === "shita") {
466
- posY = 1080 - comment.posY - comment.height;
467
- }
468
- this.context.drawImage(comment.image, posX, posY);
469
- };
470
- NiconiComments.prototype.getTextImage = function (i) {
471
- var value = this.data[i];
472
- if (value.invisible) {
473
- return;
474
- }
475
- var image = document.createElement("canvas");
476
- image.width = value.width_max;
477
- image.height = value.height;
478
- var context = image.getContext("2d");
479
- context.strokeStyle = "rgba(0,0,0,0.7)";
480
- context.textAlign = "start";
481
- context.textBaseline = "alphabetic";
482
- context.lineWidth = 4;
483
- context.font = parseFont(value.font, value.fontSize, this.useLegacy);
484
- if (value._live) {
485
- var rgb = hex2rgb(value.color);
486
- context.fillStyle = "rgba(".concat(rgb[0], ",").concat(rgb[1], ",").concat(rgb[2], ",0.5)");
487
- }
488
- else {
489
- context.fillStyle = value.color;
490
- }
491
- if (value.color === "#000000") {
492
- context.strokeStyle = "rgba(255,255,255,0.7)";
493
- }
494
- if (this.showCollision) {
495
- context.strokeStyle = "rgba(0,255,255,1)";
496
- context.strokeRect(0, 0, value.width_max, value.height);
497
- if (value.color === "#000000") {
498
- context.strokeStyle = "rgba(255,255,255,0.7)";
499
- }
500
- else {
501
- context.strokeStyle = "rgba(0,0,0,0.7)";
502
- }
503
- }
504
- var lines = value.content.split("\n");
505
- for (var i_1 in lines) {
506
- var line = lines[i_1], posY = void 0;
507
- posY = (Number(i_1) + 1) * (value.fontSize) * (1 + this.commentYPaddingTop);
508
- context.strokeText(line, 0, posY);
509
- context.fillText(line, 0, posY);
510
- if (this.showCollision) {
511
- context.strokeStyle = "rgba(255,255,0,0.5)";
512
- context.strokeRect(0, posY, value.width_max, value.fontSize * -1);
513
- if (value.color === "#000000") {
514
- context.strokeStyle = "rgba(255,255,255,0.7)";
515
- }
516
- else {
517
- context.strokeStyle = "rgba(0,0,0,0.7)";
518
- }
519
- }
520
- }
521
- this.data[i].image = image;
522
- };
523
- NiconiComments.prototype.parseCommand = function (comment) {
524
- var metadata = comment.mail, loc = null, size = null, fontSize = null, color = null, font = null, full = false, ender = false, _live = false, invisible = false, long = null;
525
- for (var i in metadata) {
526
- var command = metadata[i].toLowerCase();
527
- var match = command.match(/^@([0-9.]+)/);
528
- if (match) {
529
- long = match[1];
530
- }
531
- if (loc === null) {
532
- switch (command) {
533
- case "ue":
534
- loc = "ue";
535
- break;
536
- case "shita":
537
- loc = "shita";
538
- break;
539
- }
540
- }
541
- if (size === null) {
542
- switch (command) {
543
- case "big":
544
- size = "big";
545
- fontSize = this.fontSize.big["default"];
546
- break;
547
- case "small":
548
- size = "small";
549
- fontSize = this.fontSize.small["default"];
550
- break;
551
- }
552
- }
553
- if (color === null) {
554
- switch (command) {
555
- case "white":
556
- color = "#FFFFFF";
557
- break;
558
- case "red":
559
- color = "#FF0000";
560
- break;
561
- case "pink":
562
- color = "#FF8080";
563
- break;
564
- case "orange":
565
- color = "#FFC000";
566
- break;
567
- case "yellow":
568
- color = "#FFFF00";
569
- break;
570
- case "green":
571
- color = "#00FF00";
572
- break;
573
- case "cyan":
574
- color = "#00FFFF";
575
- break;
576
- case "blue":
577
- color = "#0000FF";
578
- break;
579
- case "purple":
580
- color = "#C000FF";
581
- break;
582
- case "black":
583
- color = "#000000";
584
- break;
585
- case "white2":
586
- case "niconicowhite":
587
- color = "#CCCC99";
588
- break;
589
- case "red2":
590
- case "truered":
591
- color = "#CC0033";
592
- break;
593
- case "pink2":
594
- color = "#FF33CC";
595
- break;
596
- case "orange2":
597
- case "passionorange":
598
- color = "#FF6600";
599
- break;
600
- case "yellow2":
601
- case "madyellow":
602
- color = "#999900";
603
- break;
604
- case "green2":
605
- case "elementalgreen":
606
- color = "#00CC66";
607
- break;
608
- case "cyan2":
609
- color = "#00CCCC";
610
- break;
611
- case "blue2":
612
- case "marineblue":
613
- color = "#3399FF";
614
- break;
615
- case "purple2":
616
- case "nobleviolet":
617
- color = "#6633CC";
618
- break;
619
- case "black2":
620
- color = "#666666";
621
- break;
622
- default:
623
- var match_1 = command.match(/#[0-9a-z]{3,6}/);
624
- if (match_1 && comment.premium) {
625
- color = match_1[0].toUpperCase();
626
- }
627
- break;
628
- }
629
- }
630
- if (font === null) {
631
- switch (command) {
632
- case "gothic":
633
- font = "gothic";
634
- break;
635
- case "mincho":
636
- font = "mincho";
637
- break;
638
- }
639
- }
640
- switch (command) {
641
- case "full":
642
- full = true;
643
- break;
644
- case "ender":
645
- ender = true;
646
- break;
647
- case "_live":
648
- _live = true;
649
- break;
650
- case "invisible":
651
- invisible = true;
652
- break;
653
- }
654
- }
655
- return { loc: loc, size: size, fontSize: fontSize, color: color, font: font, full: full, ender: ender, _live: _live, invisible: invisible, long: long };
656
- };
657
- NiconiComments.prototype.parseCommandAndNicoscript = function (comment) {
658
- comment.content = comment.content.replace("/\t/g", "  ");
659
- var data = this.parseCommand(comment), nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
660
- if (nicoscript) {
661
- switch (nicoscript[1]) {
662
- case "デフォルト":
663
- this.nicoScripts["default"].push({
664
- start: comment.vpos,
665
- long: data.long === null ? null : Math.floor(data.long * 100),
666
- color: data.color,
667
- size: data.size,
668
- font: data.font,
669
- loc: data.loc
670
- });
671
- break;
672
- case "逆":
673
- var reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
674
- if (!reverse[1]) {
675
- reverse[1] = "全";
676
- }
677
- if (data.long === null) {
678
- data.long = 30;
679
- }
680
- this.nicoScripts.reverse.push({
681
- start: comment.vpos,
682
- end: comment.vpos + (data.long * 100),
683
- target: reverse[1]
684
- });
685
- break;
686
- case "コメント禁止":
687
- if (data.long === null) {
688
- data.long = 30;
689
- }
690
- this.nicoScripts.reverse.push({
691
- start: comment.vpos,
692
- end: comment.vpos + (data.long * 100)
693
- });
694
- break;
695
- case "置換":
696
- var content = comment.content.split(""), quote = "", last_i = "", string = "", result = [];
697
- for (var _i = 0, _a = content.slice(4); _i < _a.length; _i++) {
698
- var i = _a[_i];
699
- if (i.match(/["'「]/) && quote === "") {
700
- quote = i;
701
- }
702
- else if (i.match(/["']/) && quote === i && last_i !== "\\") {
703
- result.push(replaceAll(string, "\\n", "\n"));
704
- quote = "";
705
- string = "";
706
- }
707
- else if (i.match(/」/) && quote === "「") {
708
- result.push(string);
709
- quote = "";
710
- string = "";
711
- }
712
- else if (quote === "" && i.match(/[\s ]/)) {
713
- if (string) {
714
- result.push(string);
715
- string = "";
716
- }
717
- }
718
- else {
719
- string += i;
720
- }
721
- last_i = i;
722
- }
723
- result.push(string);
724
- this.nicoScripts.replace.push({
725
- start: comment.vpos,
726
- long: data.long === null ? null : Math.floor(data.long * 100),
727
- keyword: result[0],
728
- replace: result[1] || "",
729
- range: result[2] || "単",
730
- target: result[3] || "コメ",
731
- condition: result[4] || "部分一致",
732
- color: data.color,
733
- size: data.size,
734
- font: data.font,
735
- loc: data.loc
736
- });
737
- break;
738
- }
739
- data.invisible = true;
740
- }
741
- var color = "#FFFFFF", size = "medium", font = "defont", loc = "naka";
742
- for (var i in this.nicoScripts["default"]) {
743
- if (this.nicoScripts["default"][i].long !== null && this.nicoScripts["default"][i].start + this.nicoScripts["default"][i].long < comment.vpos) {
744
- this.nicoScripts["default"] = this.nicoScripts["default"].splice(Number(i), 1);
745
- continue;
746
- }
747
- if (this.nicoScripts["default"][i].loc) {
748
- loc = this.nicoScripts["default"][i].loc;
749
- }
750
- if (this.nicoScripts["default"][i].color) {
751
- color = this.nicoScripts["default"][i].color;
752
- }
753
- if (this.nicoScripts["default"][i].size) {
754
- size = this.nicoScripts["default"][i].size;
755
- }
756
- if (this.nicoScripts["default"][i].font) {
757
- font = this.nicoScripts["default"][i].font;
758
- }
759
- }
760
- for (var i in this.nicoScripts.replace) {
761
- if (this.nicoScripts.replace[i].long !== null && this.nicoScripts.replace[i].start + this.nicoScripts.replace[i].long < comment.vpos) {
762
- this.nicoScripts["default"] = this.nicoScripts["default"].splice(Number(i), 1);
763
- continue;
764
- }
765
- var item = this.nicoScripts.replace[i];
766
- if ((item.target === "コメ" && comment.owner) || (item.target === "投コメ" && !comment.owner) || (item.target === "含まない" && comment.owner))
767
- continue;
768
- if ((item.condition === "完全一致" && comment.content === item.keyword) || (item.condition === "部分一致" && comment.content.indexOf(item.keyword) !== -1)) {
769
- if (item.range === "単") {
770
- comment.content = replaceAll(comment.content, item.keyword, item.replace);
771
- }
772
- else {
773
- comment.content = item.replace;
774
- }
775
- if (item.loc) {
776
- loc = item.loc;
777
- }
778
- if (item.color) {
779
- color = item.color;
780
- }
781
- if (item.size) {
782
- size = item.size;
783
- }
784
- if (item.font) {
785
- font = item.font;
786
- }
787
- }
788
- }
789
- if (!data.loc) {
790
- data.loc = loc;
791
- }
792
- if (!data.color) {
793
- data.color = color;
794
- }
795
- if (!data.size) {
796
- data.size = size;
797
- data.fontSize = this.fontSize[data.size]["default"];
798
- }
799
- if (!data.font) {
800
- data.font = font;
801
- }
802
- if (data.loc !== "naka") {
803
- if (!data.long) {
804
- data.long = 300;
805
- }
806
- else {
807
- data.long = Math.floor(data.long * 100);
808
- }
809
- }
810
- return __assign(__assign({}, comment), data);
811
- };
812
- NiconiComments.prototype.drawCanvas = function (vpos) {
813
- if (this.lastVpos === vpos)
814
- return;
815
- this.lastVpos = vpos;
816
- this.fpsCount++;
817
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
818
- if (this.video) {
819
- var offsetX = void 0, offsetY = void 0, scale = void 0, height = this.canvas.height / this.video.videoHeight, width = this.canvas.width / this.video.videoWidth;
820
- if (height > width) {
821
- scale = width;
822
- }
823
- else {
824
- scale = height;
825
- }
826
- offsetX = (this.canvas.width - this.video.videoWidth * scale) * 0.5;
827
- offsetY = (this.canvas.height - this.video.videoHeight * scale) * 0.5;
828
- this.context.drawImage(this.video, offsetX, offsetY, this.video.videoWidth * scale, this.video.videoHeight * scale);
829
- }
830
- if (this.timeline[vpos]) {
831
- for (var index in this.timeline[vpos]) {
832
- var comment = this.data[this.timeline[vpos][index]];
833
- if (comment.invisible) {
834
- continue;
835
- }
836
- if (!comment.image) {
837
- this.getTextImage(this.timeline[vpos][index]);
838
- }
839
- this.drawText(comment, vpos);
840
- }
841
- }
842
- if (this.showFPS) {
843
- this.context.font = parseFont("defont", 60, this.useLegacy);
844
- this.context.fillStyle = "#00FF00";
845
- this.context.strokeText("FPS:" + this.fps, 100, 100);
846
- this.context.fillText("FPS:" + this.fps, 100, 100);
847
- }
848
- if (this.showCommentCount) {
849
- this.context.font = parseFont("defont", 60, this.useLegacy);
850
- this.context.fillStyle = "#00FF00";
851
- if (this.timeline[vpos]) {
852
- this.context.strokeText("Count:" + this.timeline[vpos].length, 100, 200);
853
- this.context.fillText("Count:" + this.timeline[vpos].length, 100, 200);
854
- }
855
- else {
856
- this.context.strokeText("Count:0", 100, 200);
857
- this.context.fillText("Count:0", 100, 200);
858
- }
859
- }
860
- };
861
- NiconiComments.prototype.clear = function () {
862
- this.context.clearRect(0, 0, 1920, 1080);
863
- };
864
- return NiconiComments;
865
- }());
866
- var groupBy = function (array, key, key2) {
867
- var data = {};
868
- for (var i in array) {
869
- if (!data[array[i][key]]) {
870
- data[array[i][key]] = {};
871
- }
872
- if (!data[array[i][key]][array[i][key2]]) {
873
- data[array[i][key]][array[i][key2]] = [];
874
- }
875
- array[i].index = i;
876
- data[array[i][key]][array[i][key2]].push(array[i]);
877
- }
878
- return data;
879
- };
880
- var parseFont = function (font, size, useLegacy) {
881
- switch (font) {
882
- case "gothic":
883
- return "normal 400 ".concat(size, "px \"\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53\", \"\u6E38\u30B4\u30B7\u30C3\u30AF\", \"Yu Gothic\", YuGothic, yugothic, YuGo-Medium");
884
- case "mincho":
885
- return "normal 400 ".concat(size, "px \"\u6E38\u660E\u671D\u4F53\", \"\u6E38\u660E\u671D\", \"Yu Mincho\", YuMincho, yumincho, YuMin-Medium");
886
- default:
887
- if (useLegacy) {
888
- return "normal 600 ".concat(size, "px Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
889
- }
890
- else {
891
- return "normal 600 ".concat(size, "px sans-serif, Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
892
- }
893
- }
894
- };
895
- var arrayPush = function (array, key, push) {
896
- if (!array) {
897
- array = {};
898
- }
899
- if (!array[key]) {
900
- array[key] = [];
901
- }
902
- array[key].push(push);
903
- };
904
- var hex2rgb = function (hex) {
905
- if (hex.slice(0, 1) === "#")
906
- hex = hex.slice(1);
907
- if (hex.length === 3)
908
- hex = hex.slice(0, 1) + hex.slice(0, 1) + hex.slice(1, 2) + hex.slice(1, 2) + hex.slice(2, 3) + hex.slice(2, 3);
909
- return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)].map(function (str) {
910
- return parseInt(str, 16);
911
- });
912
- };
913
- var replaceAll = function (string, target, replace) {
914
- var count = 0;
915
- while (string.indexOf(target) !== -1 && count < 100) {
916
- string = string.replace(target, replace);
917
- count++;
918
- }
919
- return string;
40
+ var NiconiComments = (function () {
41
+ function NiconiComments(canvas, data, options) {
42
+ if (options === void 0) { options = {
43
+ useLegacy: false,
44
+ formatted: false,
45
+ video: null,
46
+ showCollision: false,
47
+ showFPS: false,
48
+ showCommentCount: false,
49
+ drawAllImageOnLoad: false
50
+ }; }
51
+ var _this = this;
52
+ this.canvas = canvas;
53
+ this.context = canvas.getContext("2d");
54
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
55
+ this.context.textAlign = "start";
56
+ this.context.textBaseline = "alphabetic";
57
+ this.context.lineWidth = 4;
58
+ this.commentYPaddingTop = 0.08;
59
+ this.commentYMarginBottom = 0.24;
60
+ this.fontSize = {
61
+ "small": {
62
+ "default": 47,
63
+ "resized": 26.1
64
+ },
65
+ "medium": {
66
+ "default": 74,
67
+ "resized": 38.7
68
+ },
69
+ "big": {
70
+ "default": 111,
71
+ "resized": 62
72
+ }
73
+ };
74
+ this.doubleResizeMaxWidth = {
75
+ full: {
76
+ legacy: 3020,
77
+ "default": 3220
78
+ },
79
+ normal: {
80
+ legacy: 2540,
81
+ "default": 2740
82
+ }
83
+ };
84
+ var parsedData = options.formatted ? data : this.parseData(data);
85
+ this.video = options.video ? options.video : null;
86
+ this.showCollision = options.showCollision;
87
+ this.showFPS = options.showFPS;
88
+ this.showCommentCount = options.showCommentCount;
89
+ this.timeline = {};
90
+ this.nicoScripts = { reverse: [], "default": [], replace: [], ban: [] };
91
+ this.collision_right = {};
92
+ this.collision_left = {};
93
+ this.collision_ue = {};
94
+ this.collision_shita = {};
95
+ this.lastVpos = -1;
96
+ this.useLegacy = options.useLegacy;
97
+ this.preRendering(parsedData, options.drawAllImageOnLoad);
98
+ this.fpsCount = 0;
99
+ this.fps = 0;
100
+ this.fpsClock = window.setInterval(function () {
101
+ _this.fps = _this.fpsCount * 2;
102
+ _this.fpsCount = 0;
103
+ }, 500);
104
+ }
105
+ NiconiComments.prototype.parseData = function (data) {
106
+ var data_ = [];
107
+ for (var i = 0; i < data.length; i++) {
108
+ for (var key in data[i]) {
109
+ var value = data[i][key];
110
+ if (key === "chat" && value["deleted"] !== 1) {
111
+ var tmpParam = {
112
+ "id": value["no"],
113
+ "vpos": value["vpos"],
114
+ "content": value["content"],
115
+ "date": value["date"],
116
+ "date_usec": value["date_usec"],
117
+ "owner": !value["user_id"],
118
+ "premium": value["premium"] === 1,
119
+ "mail": []
120
+ };
121
+ if (value["mail"]) {
122
+ tmpParam["mail"] = value["mail"].split(/[\s ]/g);
123
+ }
124
+ if (value["content"].startsWith("/") && !value["user_id"]) {
125
+ tmpParam["mail"].push("invisible");
126
+ }
127
+ data_.push(tmpParam);
128
+ }
129
+ }
130
+ }
131
+ data_.sort(function (a, b) {
132
+ if (a.vpos < b.vpos)
133
+ return -1;
134
+ if (a.vpos > b.vpos)
135
+ return 1;
136
+ if (a.date < b.date)
137
+ return -1;
138
+ if (a.date > b.date)
139
+ return 1;
140
+ if (a.date_usec < b.date_usec)
141
+ return -1;
142
+ if (a.date_usec > b.date_usec)
143
+ return 1;
144
+ return 0;
145
+ });
146
+ return data_;
147
+ };
148
+ NiconiComments.prototype.preRendering = function (rawData, drawAll) {
149
+ var parsedData = this.getCommentPos(this.getCommentSize(this.getFont(rawData)));
150
+ this.data = this.sortComment(parsedData);
151
+ if (drawAll) {
152
+ for (var i in parsedData) {
153
+ this.getTextImage(Number(i));
154
+ }
155
+ }
156
+ };
157
+ NiconiComments.prototype.getFont = function (parsedData) {
158
+ var result = [];
159
+ for (var i in parsedData) {
160
+ result[i] = this.parseCommandAndNicoscript(parsedData[i]);
161
+ }
162
+ return result;
163
+ };
164
+ NiconiComments.prototype.getCommentSize = function (parsedData) {
165
+ var tmpData = groupBy(parsedData, "font", "fontSize");
166
+ var result = [];
167
+ for (var i in tmpData) {
168
+ for (var j in tmpData[i]) {
169
+ this.context.font = parseFont(i, j, this.useLegacy);
170
+ for (var k in tmpData[i][j]) {
171
+ var comment = tmpData[i][j][k];
172
+ if (comment.invisible) {
173
+ continue;
174
+ }
175
+ var measure = this.measureText(comment);
176
+ result[comment.index] = parsedData[comment.index];
177
+ result[comment.index].height = measure.height;
178
+ result[comment.index].width = measure.width;
179
+ result[comment.index].width_max = measure.width_max;
180
+ result[comment.index].width_min = measure.width_min;
181
+ if (measure.resized) {
182
+ result[comment.index].fontSize = measure.fontSize;
183
+ this.context.font = parseFont(i, j, this.useLegacy);
184
+ }
185
+ }
186
+ }
187
+ }
188
+ return result;
189
+ };
190
+ NiconiComments.prototype.getCommentPos = function (parsedData) {
191
+ var data = parsedData;
192
+ for (var i in data) {
193
+ var comment = data[i];
194
+ if (comment.invisible) {
195
+ continue;
196
+ }
197
+ for (var j = 0; j < 500; j++) {
198
+ if (!this.timeline[comment.vpos + j]) {
199
+ this.timeline[comment.vpos + j] = [];
200
+ }
201
+ if (!this.collision_right[comment.vpos + j]) {
202
+ this.collision_right[comment.vpos + j] = [];
203
+ }
204
+ if (!this.collision_left[comment.vpos + j]) {
205
+ this.collision_left[comment.vpos + j] = [];
206
+ }
207
+ if (!this.collision_ue[comment.vpos + j]) {
208
+ this.collision_ue[comment.vpos + j] = [];
209
+ }
210
+ if (!this.collision_shita[comment.vpos + j]) {
211
+ this.collision_shita[comment.vpos + j] = [];
212
+ }
213
+ }
214
+ if (comment.loc === "naka") {
215
+ comment.vpos -= 70;
216
+ parsedData[i].vpos -= 70;
217
+ var posY = 0, is_break = false, is_change = true, count = 0;
218
+ if (1080 < comment.height) {
219
+ posY = (comment.height - 1080) / -2;
220
+ }
221
+ else {
222
+ while (is_change && count < 10) {
223
+ is_change = false;
224
+ count++;
225
+ for (var j = 0; j < 500; j++) {
226
+ var vpos = comment.vpos + j;
227
+ var left_pos = 1920 - ((1920 + comment.width_max) * j / 500);
228
+ if (left_pos + comment.width_max >= 1880) {
229
+ for (var k in this.collision_right[vpos]) {
230
+ var l = this.collision_right[vpos][k];
231
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
232
+ if (data[l].posY + data[l].height > posY) {
233
+ posY = data[l].posY + data[l].height;
234
+ is_change = true;
235
+ }
236
+ if (posY + comment.height > 1080) {
237
+ if (1080 < comment.height) {
238
+ posY = (comment.height - 1080) / -2;
239
+ }
240
+ else {
241
+ posY = Math.floor(Math.random() * (1080 - comment.height));
242
+ }
243
+ is_break = true;
244
+ break;
245
+ }
246
+ }
247
+ }
248
+ if (is_break) {
249
+ break;
250
+ }
251
+ }
252
+ if (left_pos <= 40 && is_break === false) {
253
+ for (var k in this.collision_left[vpos]) {
254
+ var l = this.collision_left[vpos][k];
255
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
256
+ if (data[l].posY + data[l].height > posY) {
257
+ posY = data[l].posY + data[l].height;
258
+ is_change = true;
259
+ }
260
+ if (posY + comment.height > 1080) {
261
+ if (1080 < comment.height) {
262
+ posY = 0;
263
+ }
264
+ else {
265
+ posY = Math.random() * (1080 - comment.height);
266
+ }
267
+ is_break = true;
268
+ break;
269
+ }
270
+ }
271
+ }
272
+ if (is_break) {
273
+ break;
274
+ }
275
+ }
276
+ if (is_break) {
277
+ break;
278
+ }
279
+ }
280
+ }
281
+ }
282
+ for (var j = 0; j < 500; j++) {
283
+ var vpos = comment.vpos + j;
284
+ var left_pos = 1920 - ((1920 + comment.width_max) * j / 500);
285
+ arrayPush(this.timeline, vpos, i);
286
+ if (left_pos + comment.width_max >= 1880) {
287
+ arrayPush(this.collision_right, vpos, i);
288
+ }
289
+ if (left_pos <= 40) {
290
+ arrayPush(this.collision_left, vpos, i);
291
+ }
292
+ }
293
+ parsedData[i].posY = posY;
294
+ }
295
+ else {
296
+ var posY = 0, is_break = false, is_change = true, count = 0, collision = void 0;
297
+ if (comment.loc === "ue") {
298
+ collision = this.collision_ue;
299
+ }
300
+ else if (comment.loc === "shita") {
301
+ collision = this.collision_shita;
302
+ }
303
+ while (is_change && count < 10) {
304
+ is_change = false;
305
+ count++;
306
+ for (var j = 0; j < 300; j++) {
307
+ var vpos = comment.vpos + j;
308
+ for (var k in collision[vpos]) {
309
+ var l = collision[vpos][k];
310
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner) {
311
+ if (data[l].posY + data[l].height > posY) {
312
+ posY = data[l].posY + data[l].height;
313
+ is_change = true;
314
+ }
315
+ if (posY + comment.height > 1080) {
316
+ if (1000 <= comment.height) {
317
+ posY = 0;
318
+ }
319
+ else {
320
+ posY = Math.floor(Math.random() * (1080 - comment.height));
321
+ }
322
+ is_break = true;
323
+ break;
324
+ }
325
+ }
326
+ }
327
+ if (is_break) {
328
+ break;
329
+ }
330
+ }
331
+ }
332
+ for (var j = 0; j < comment.long; j++) {
333
+ var vpos = comment.vpos + j;
334
+ arrayPush(this.timeline, vpos, i);
335
+ if (comment.loc === "ue") {
336
+ arrayPush(this.collision_ue, vpos, i);
337
+ }
338
+ else {
339
+ arrayPush(this.collision_shita, vpos, i);
340
+ }
341
+ }
342
+ parsedData[i].posY = posY;
343
+ }
344
+ }
345
+ return parsedData;
346
+ };
347
+ NiconiComments.prototype.sortComment = function (parsedData) {
348
+ for (var vpos in this.timeline) {
349
+ this.timeline[vpos].sort(function (a, b) {
350
+ var A = parsedData[a];
351
+ var B = parsedData[b];
352
+ if (!A.owner && B.owner) {
353
+ return -1;
354
+ }
355
+ else if (A.owner && !B.owner) {
356
+ return 1;
357
+ }
358
+ else {
359
+ return 0;
360
+ }
361
+ });
362
+ }
363
+ return parsedData;
364
+ };
365
+ NiconiComments.prototype.measureText = function (comment) {
366
+ var width, width_max, width_min, height, width_arr = [], lines = comment.content.split("\n");
367
+ if (!comment.resized && !comment.ender) {
368
+ if (comment.size === "big" && lines.length > 2) {
369
+ comment.fontSize = this.fontSize.big.resized;
370
+ comment.resized = true;
371
+ comment.tateresized = true;
372
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
373
+ }
374
+ else if (comment.size === "medium" && lines.length > 4) {
375
+ comment.fontSize = this.fontSize.medium.resized;
376
+ comment.resized = true;
377
+ comment.tateresized = true;
378
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
379
+ }
380
+ else if (comment.size === "small" && lines.length > 6) {
381
+ comment.fontSize = this.fontSize.small.resized;
382
+ comment.resized = true;
383
+ comment.tateresized = true;
384
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
385
+ }
386
+ }
387
+ for (var i = 0; i < lines.length; i++) {
388
+ var measure = this.context.measureText(lines[i]);
389
+ width_arr.push(measure.width);
390
+ }
391
+ width = width_arr.reduce(function (p, c) { return p + c; }, 0) / width_arr.length;
392
+ width_max = Math.max.apply(Math, width_arr);
393
+ width_min = Math.min.apply(Math, width_arr);
394
+ height = (comment.fontSize * (1 + this.commentYPaddingTop) * lines.length) + (this.commentYMarginBottom * comment.fontSize);
395
+ if (comment.loc !== "naka" && !comment.tateresized) {
396
+ if (comment.full && width_max > 1920) {
397
+ comment.fontSize -= 1;
398
+ comment.resized = true;
399
+ comment.yokoResized = true;
400
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
401
+ return this.measureText(comment);
402
+ }
403
+ else if (!comment.full && width_max > 1440) {
404
+ comment.fontSize -= 1;
405
+ comment.resized = true;
406
+ comment.yokoResized = true;
407
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
408
+ return this.measureText(comment);
409
+ }
410
+ }
411
+ else if (comment.loc !== "naka" && comment.tateresized && (comment.full && width_max > 1920 || !comment.full && width_max > 1440) && !comment.yokoResized) {
412
+ comment.fontSize = this.fontSize[comment.size]["default"];
413
+ comment.resized = true;
414
+ comment.yokoResized = true;
415
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
416
+ return this.measureText(comment);
417
+ }
418
+ else if (comment.loc !== "naka" && comment.tateresized && comment.yokoResized) {
419
+ if (comment.full && width_max > this.doubleResizeMaxWidth.full[this.useLegacy ? "legacy" : "default"]) {
420
+ comment.fontSize -= 1;
421
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
422
+ return this.measureText(comment);
423
+ }
424
+ else if (!comment.full && width_max > this.doubleResizeMaxWidth.normal[this.useLegacy ? "legacy" : "default"]) {
425
+ comment.fontSize -= 1.;
426
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
427
+ return this.measureText(comment);
428
+ }
429
+ }
430
+ return {
431
+ "width": width,
432
+ "width_max": width_max,
433
+ "width_min": width_min,
434
+ "height": height,
435
+ "resized": comment.resized,
436
+ "fontSize": comment.fontSize
437
+ };
438
+ };
439
+ NiconiComments.prototype.drawText = function (comment, vpos) {
440
+ var reverse = false;
441
+ for (var i in this.nicoScripts.reverse) {
442
+ var range = this.nicoScripts.reverse[i];
443
+ if ((range.target === "コメ" && comment.owner) || (range.target === "投コメ" && !comment.owner)) {
444
+ break;
445
+ }
446
+ if (range.start < vpos && vpos < range.end) {
447
+ reverse = true;
448
+ }
449
+ }
450
+ for (var i in this.nicoScripts.ban) {
451
+ var range = this.nicoScripts.ban[i];
452
+ if (range.start < vpos && vpos < range.end) {
453
+ return;
454
+ }
455
+ }
456
+ var posX = (1920 - comment.width_max) / 2, posY = comment.posY;
457
+ if (comment.loc === "naka") {
458
+ if (reverse) {
459
+ posX = ((1920 + comment.width_max) * (vpos - comment.vpos) / 500) - comment.width_max;
460
+ }
461
+ else {
462
+ posX = 1920 - ((1920 + comment.width_max) * (vpos - comment.vpos) / 500);
463
+ }
464
+ }
465
+ else if (comment.loc === "shita") {
466
+ posY = 1080 - comment.posY - comment.height;
467
+ }
468
+ this.context.drawImage(comment.image, posX, posY);
469
+ };
470
+ NiconiComments.prototype.getTextImage = function (i) {
471
+ var value = this.data[i];
472
+ if (value.invisible) {
473
+ return;
474
+ }
475
+ var image = document.createElement("canvas");
476
+ image.width = value.width_max;
477
+ image.height = value.height;
478
+ var context = image.getContext("2d");
479
+ context.strokeStyle = "rgba(0,0,0,0.7)";
480
+ context.textAlign = "start";
481
+ context.textBaseline = "alphabetic";
482
+ context.lineWidth = 4;
483
+ context.font = parseFont(value.font, value.fontSize, this.useLegacy);
484
+ if (value._live) {
485
+ var rgb = hex2rgb(value.color);
486
+ context.fillStyle = "rgba(".concat(rgb[0], ",").concat(rgb[1], ",").concat(rgb[2], ",0.5)");
487
+ }
488
+ else {
489
+ context.fillStyle = value.color;
490
+ }
491
+ if (value.color === "#000000") {
492
+ context.strokeStyle = "rgba(255,255,255,0.7)";
493
+ }
494
+ if (this.showCollision) {
495
+ context.strokeStyle = "rgba(0,255,255,1)";
496
+ context.strokeRect(0, 0, value.width_max, value.height);
497
+ if (value.color === "#000000") {
498
+ context.strokeStyle = "rgba(255,255,255,0.7)";
499
+ }
500
+ else {
501
+ context.strokeStyle = "rgba(0,0,0,0.7)";
502
+ }
503
+ }
504
+ var lines = value.content.split("\n");
505
+ for (var i_1 in lines) {
506
+ var line = lines[i_1], posY = void 0;
507
+ posY = (Number(i_1) + 1) * (value.fontSize) * (1 + this.commentYPaddingTop);
508
+ context.strokeText(line, 0, posY);
509
+ context.fillText(line, 0, posY);
510
+ if (this.showCollision) {
511
+ context.strokeStyle = "rgba(255,255,0,0.5)";
512
+ context.strokeRect(0, posY, value.width_max, value.fontSize * -1);
513
+ if (value.color === "#000000") {
514
+ context.strokeStyle = "rgba(255,255,255,0.7)";
515
+ }
516
+ else {
517
+ context.strokeStyle = "rgba(0,0,0,0.7)";
518
+ }
519
+ }
520
+ }
521
+ this.data[i].image = image;
522
+ };
523
+ NiconiComments.prototype.parseCommand = function (comment) {
524
+ var metadata = comment.mail, loc = null, size = null, fontSize = null, color = null, font = null, full = false, ender = false, _live = false, invisible = false, long = null;
525
+ for (var i in metadata) {
526
+ var command = metadata[i].toLowerCase();
527
+ var match = command.match(/^@([0-9.]+)/);
528
+ if (match) {
529
+ long = match[1];
530
+ }
531
+ if (loc === null) {
532
+ switch (command) {
533
+ case "ue":
534
+ loc = "ue";
535
+ break;
536
+ case "shita":
537
+ loc = "shita";
538
+ break;
539
+ }
540
+ }
541
+ if (size === null) {
542
+ switch (command) {
543
+ case "big":
544
+ size = "big";
545
+ fontSize = this.fontSize.big["default"];
546
+ break;
547
+ case "small":
548
+ size = "small";
549
+ fontSize = this.fontSize.small["default"];
550
+ break;
551
+ }
552
+ }
553
+ if (color === null) {
554
+ switch (command) {
555
+ case "white":
556
+ color = "#FFFFFF";
557
+ break;
558
+ case "red":
559
+ color = "#FF0000";
560
+ break;
561
+ case "pink":
562
+ color = "#FF8080";
563
+ break;
564
+ case "orange":
565
+ color = "#FFC000";
566
+ break;
567
+ case "yellow":
568
+ color = "#FFFF00";
569
+ break;
570
+ case "green":
571
+ color = "#00FF00";
572
+ break;
573
+ case "cyan":
574
+ color = "#00FFFF";
575
+ break;
576
+ case "blue":
577
+ color = "#0000FF";
578
+ break;
579
+ case "purple":
580
+ color = "#C000FF";
581
+ break;
582
+ case "black":
583
+ color = "#000000";
584
+ break;
585
+ case "white2":
586
+ case "niconicowhite":
587
+ color = "#CCCC99";
588
+ break;
589
+ case "red2":
590
+ case "truered":
591
+ color = "#CC0033";
592
+ break;
593
+ case "pink2":
594
+ color = "#FF33CC";
595
+ break;
596
+ case "orange2":
597
+ case "passionorange":
598
+ color = "#FF6600";
599
+ break;
600
+ case "yellow2":
601
+ case "madyellow":
602
+ color = "#999900";
603
+ break;
604
+ case "green2":
605
+ case "elementalgreen":
606
+ color = "#00CC66";
607
+ break;
608
+ case "cyan2":
609
+ color = "#00CCCC";
610
+ break;
611
+ case "blue2":
612
+ case "marineblue":
613
+ color = "#3399FF";
614
+ break;
615
+ case "purple2":
616
+ case "nobleviolet":
617
+ color = "#6633CC";
618
+ break;
619
+ case "black2":
620
+ color = "#666666";
621
+ break;
622
+ default:
623
+ var match_1 = command.match(/#[0-9a-z]{3,6}/);
624
+ if (match_1 && comment.premium) {
625
+ color = match_1[0].toUpperCase();
626
+ }
627
+ break;
628
+ }
629
+ }
630
+ if (font === null) {
631
+ switch (command) {
632
+ case "gothic":
633
+ font = "gothic";
634
+ break;
635
+ case "mincho":
636
+ font = "mincho";
637
+ break;
638
+ }
639
+ }
640
+ switch (command) {
641
+ case "full":
642
+ full = true;
643
+ break;
644
+ case "ender":
645
+ ender = true;
646
+ break;
647
+ case "_live":
648
+ _live = true;
649
+ break;
650
+ case "invisible":
651
+ invisible = true;
652
+ break;
653
+ }
654
+ }
655
+ return { loc: loc, size: size, fontSize: fontSize, color: color, font: font, full: full, ender: ender, _live: _live, invisible: invisible, long: long };
656
+ };
657
+ NiconiComments.prototype.parseCommandAndNicoscript = function (comment) {
658
+ comment.content = comment.content.replace("/\t/g", "  ");
659
+ var data = this.parseCommand(comment), nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
660
+ if (nicoscript) {
661
+ switch (nicoscript[1]) {
662
+ case "デフォルト":
663
+ this.nicoScripts["default"].push({
664
+ start: comment.vpos,
665
+ long: data.long === null ? null : Math.floor(data.long * 100),
666
+ color: data.color,
667
+ size: data.size,
668
+ font: data.font,
669
+ loc: data.loc
670
+ });
671
+ break;
672
+ case "逆":
673
+ var reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
674
+ if (!reverse[1]) {
675
+ reverse[1] = "全";
676
+ }
677
+ if (data.long === null) {
678
+ data.long = 30;
679
+ }
680
+ this.nicoScripts.reverse.push({
681
+ start: comment.vpos,
682
+ end: comment.vpos + (data.long * 100),
683
+ target: reverse[1]
684
+ });
685
+ break;
686
+ case "コメント禁止":
687
+ if (data.long === null) {
688
+ data.long = 30;
689
+ }
690
+ this.nicoScripts.reverse.push({
691
+ start: comment.vpos,
692
+ end: comment.vpos + (data.long * 100)
693
+ });
694
+ break;
695
+ case "置換":
696
+ var content = comment.content.split(""), quote = "", last_i = "", string = "", result = [];
697
+ for (var _i = 0, _a = content.slice(4); _i < _a.length; _i++) {
698
+ var i = _a[_i];
699
+ if (i.match(/["'「]/) && quote === "") {
700
+ quote = i;
701
+ }
702
+ else if (i.match(/["']/) && quote === i && last_i !== "\\") {
703
+ result.push(replaceAll(string, "\\n", "\n"));
704
+ quote = "";
705
+ string = "";
706
+ }
707
+ else if (i.match(/」/) && quote === "「") {
708
+ result.push(string);
709
+ quote = "";
710
+ string = "";
711
+ }
712
+ else if (quote === "" && i.match(/[\s ]/)) {
713
+ if (string) {
714
+ result.push(string);
715
+ string = "";
716
+ }
717
+ }
718
+ else {
719
+ string += i;
720
+ }
721
+ last_i = i;
722
+ }
723
+ result.push(string);
724
+ this.nicoScripts.replace.push({
725
+ start: comment.vpos,
726
+ long: data.long === null ? null : Math.floor(data.long * 100),
727
+ keyword: result[0],
728
+ replace: result[1] || "",
729
+ range: result[2] || "単",
730
+ target: result[3] || "コメ",
731
+ condition: result[4] || "部分一致",
732
+ color: data.color,
733
+ size: data.size,
734
+ font: data.font,
735
+ loc: data.loc
736
+ });
737
+ break;
738
+ }
739
+ data.invisible = true;
740
+ }
741
+ var color = "#FFFFFF", size = "medium", font = "defont", loc = "naka";
742
+ for (var i in this.nicoScripts["default"]) {
743
+ if (this.nicoScripts["default"][i].long !== null && this.nicoScripts["default"][i].start + this.nicoScripts["default"][i].long < comment.vpos) {
744
+ this.nicoScripts["default"] = this.nicoScripts["default"].splice(Number(i), 1);
745
+ continue;
746
+ }
747
+ if (this.nicoScripts["default"][i].loc) {
748
+ loc = this.nicoScripts["default"][i].loc;
749
+ }
750
+ if (this.nicoScripts["default"][i].color) {
751
+ color = this.nicoScripts["default"][i].color;
752
+ }
753
+ if (this.nicoScripts["default"][i].size) {
754
+ size = this.nicoScripts["default"][i].size;
755
+ }
756
+ if (this.nicoScripts["default"][i].font) {
757
+ font = this.nicoScripts["default"][i].font;
758
+ }
759
+ }
760
+ for (var i in this.nicoScripts.replace) {
761
+ if (this.nicoScripts.replace[i].long !== null && this.nicoScripts.replace[i].start + this.nicoScripts.replace[i].long < comment.vpos) {
762
+ this.nicoScripts["default"] = this.nicoScripts["default"].splice(Number(i), 1);
763
+ continue;
764
+ }
765
+ var item = this.nicoScripts.replace[i];
766
+ if ((item.target === "コメ" && comment.owner) || (item.target === "投コメ" && !comment.owner) || (item.target === "含まない" && comment.owner))
767
+ continue;
768
+ if ((item.condition === "完全一致" && comment.content === item.keyword) || (item.condition === "部分一致" && comment.content.indexOf(item.keyword) !== -1)) {
769
+ if (item.range === "単") {
770
+ comment.content = replaceAll(comment.content, item.keyword, item.replace);
771
+ }
772
+ else {
773
+ comment.content = item.replace;
774
+ }
775
+ if (item.loc) {
776
+ loc = item.loc;
777
+ }
778
+ if (item.color) {
779
+ color = item.color;
780
+ }
781
+ if (item.size) {
782
+ size = item.size;
783
+ }
784
+ if (item.font) {
785
+ font = item.font;
786
+ }
787
+ }
788
+ }
789
+ if (!data.loc) {
790
+ data.loc = loc;
791
+ }
792
+ if (!data.color) {
793
+ data.color = color;
794
+ }
795
+ if (!data.size) {
796
+ data.size = size;
797
+ data.fontSize = this.fontSize[data.size]["default"];
798
+ }
799
+ if (!data.font) {
800
+ data.font = font;
801
+ }
802
+ if (data.loc !== "naka") {
803
+ if (!data.long) {
804
+ data.long = 300;
805
+ }
806
+ else {
807
+ data.long = Math.floor(data.long * 100);
808
+ }
809
+ }
810
+ return __assign(__assign({}, comment), data);
811
+ };
812
+ NiconiComments.prototype.drawCanvas = function (vpos) {
813
+ if (this.lastVpos === vpos)
814
+ return;
815
+ this.lastVpos = vpos;
816
+ this.fpsCount++;
817
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
818
+ if (this.video) {
819
+ var offsetX = void 0, offsetY = void 0, scale = void 0, height = this.canvas.height / this.video.videoHeight, width = this.canvas.width / this.video.videoWidth;
820
+ if (height > width) {
821
+ scale = width;
822
+ }
823
+ else {
824
+ scale = height;
825
+ }
826
+ offsetX = (this.canvas.width - this.video.videoWidth * scale) * 0.5;
827
+ offsetY = (this.canvas.height - this.video.videoHeight * scale) * 0.5;
828
+ this.context.drawImage(this.video, offsetX, offsetY, this.video.videoWidth * scale, this.video.videoHeight * scale);
829
+ }
830
+ if (this.timeline[vpos]) {
831
+ for (var index in this.timeline[vpos]) {
832
+ var comment = this.data[this.timeline[vpos][index]];
833
+ if (comment.invisible) {
834
+ continue;
835
+ }
836
+ if (!comment.image) {
837
+ this.getTextImage(this.timeline[vpos][index]);
838
+ }
839
+ this.drawText(comment, vpos);
840
+ }
841
+ }
842
+ if (this.showFPS) {
843
+ this.context.font = parseFont("defont", 60, this.useLegacy);
844
+ this.context.fillStyle = "#00FF00";
845
+ this.context.strokeText("FPS:" + this.fps, 100, 100);
846
+ this.context.fillText("FPS:" + this.fps, 100, 100);
847
+ }
848
+ if (this.showCommentCount) {
849
+ this.context.font = parseFont("defont", 60, this.useLegacy);
850
+ this.context.fillStyle = "#00FF00";
851
+ if (this.timeline[vpos]) {
852
+ this.context.strokeText("Count:" + this.timeline[vpos].length, 100, 200);
853
+ this.context.fillText("Count:" + this.timeline[vpos].length, 100, 200);
854
+ }
855
+ else {
856
+ this.context.strokeText("Count:0", 100, 200);
857
+ this.context.fillText("Count:0", 100, 200);
858
+ }
859
+ }
860
+ };
861
+ NiconiComments.prototype.clear = function () {
862
+ this.context.clearRect(0, 0, 1920, 1080);
863
+ };
864
+ return NiconiComments;
865
+ }());
866
+ var groupBy = function (array, key, key2) {
867
+ var data = {};
868
+ for (var i in array) {
869
+ if (!data[array[i][key]]) {
870
+ data[array[i][key]] = {};
871
+ }
872
+ if (!data[array[i][key]][array[i][key2]]) {
873
+ data[array[i][key]][array[i][key2]] = [];
874
+ }
875
+ array[i].index = i;
876
+ data[array[i][key]][array[i][key2]].push(array[i]);
877
+ }
878
+ return data;
879
+ };
880
+ var parseFont = function (font, size, useLegacy) {
881
+ switch (font) {
882
+ case "gothic":
883
+ return "normal 400 ".concat(size, "px \"\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53\", \"\u6E38\u30B4\u30B7\u30C3\u30AF\", \"Yu Gothic\", YuGothic, yugothic, YuGo-Medium");
884
+ case "mincho":
885
+ return "normal 400 ".concat(size, "px \"\u6E38\u660E\u671D\u4F53\", \"\u6E38\u660E\u671D\", \"Yu Mincho\", YuMincho, yumincho, YuMin-Medium");
886
+ default:
887
+ if (useLegacy) {
888
+ return "normal 600 ".concat(size, "px Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
889
+ }
890
+ else {
891
+ return "normal 600 ".concat(size, "px sans-serif, Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
892
+ }
893
+ }
894
+ };
895
+ var arrayPush = function (array, key, push) {
896
+ if (!array) {
897
+ array = {};
898
+ }
899
+ if (!array[key]) {
900
+ array[key] = [];
901
+ }
902
+ array[key].push(push);
903
+ };
904
+ var hex2rgb = function (hex) {
905
+ if (hex.slice(0, 1) === "#")
906
+ hex = hex.slice(1);
907
+ if (hex.length === 3)
908
+ hex = hex.slice(0, 1) + hex.slice(0, 1) + hex.slice(1, 2) + hex.slice(1, 2) + hex.slice(2, 3) + hex.slice(2, 3);
909
+ return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)].map(function (str) {
910
+ return parseInt(str, 16);
911
+ });
912
+ };
913
+ var replaceAll = function (string, target, replace) {
914
+ var count = 0;
915
+ while (string.indexOf(target) !== -1 && count < 100) {
916
+ string = string.replace(target, replace);
917
+ count++;
918
+ }
919
+ return string;
920
920
  };
921
921
 
922
922
  return NiconiComments;