canvas.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /* eslint no-var: 0, camelcase: 0 */
  2. var eventLeftMargin = 180;
  3. var eventRightMargin = 0;
  4. function canvasLoadEventUpdate(canvas, minTime, maxTime, events) {
  5. var event;
  6. var start;
  7. var ctx = canvas.getContext('2d');
  8. for (var i = 0, y_offset = 20; i < events.length; i++) {
  9. event = events[i];
  10. start = event.time;
  11. // var end = event.time + event.duration + event.latency;
  12. if (start >= minTime && start <= maxTime) {
  13. y_offset += 20;
  14. }
  15. }
  16. canvas.height = y_offset;
  17. ctx.fillStyle = 'green';
  18. ctx.globalAlpha = 0.5;
  19. ctx.fillRect(0, 0, eventLeftMargin, canvas.height);
  20. ctx.fillRect(
  21. canvas.width - eventRightMargin,
  22. 0,
  23. eventRightMargin,
  24. canvas.height
  25. );
  26. ctx.globalAlpha = 1;
  27. // draw legend
  28. var x_offset = 5;
  29. ctx.font = '12px Arial';
  30. var legend = 'load event';
  31. ctx.fillStyle = 'black';
  32. ctx.fillText(legend, x_offset, 15);
  33. x_offset = eventLeftMargin + 5;
  34. legend = 'start - end';
  35. ctx.fillStyle = 'black';
  36. ctx.fillText(legend, x_offset, 15);
  37. x_offset += ctx.measureText(legend).width + 5;
  38. legend = '[latency';
  39. ctx.fillStyle = 'orange';
  40. ctx.fillText(legend, x_offset, 15);
  41. x_offset += ctx.measureText(legend).width + 5;
  42. legend = 'loading';
  43. ctx.fillStyle = 'green';
  44. ctx.fillText(legend, x_offset, 15);
  45. x_offset += ctx.measureText(legend).width + 5;
  46. legend = 'parsing';
  47. ctx.fillStyle = 'blue';
  48. ctx.fillText(legend, x_offset, 15);
  49. x_offset += ctx.measureText(legend).width + 5;
  50. legend = 'appending]';
  51. ctx.fillStyle = 'red';
  52. ctx.fillText(legend, x_offset, 15);
  53. x_offset += ctx.measureText(legend).width + 5;
  54. legend = 'size bitrate';
  55. ctx.fillStyle = 'black';
  56. ctx.fillText(legend, x_offset, 15);
  57. x_offset += ctx.measureText(legend).width + 5;
  58. for (i = 0, y_offset = 20; i < events.length; i++) {
  59. event = events[i];
  60. start = Math.round(event.time);
  61. // var end = Math.round(event.time + event.duration + event.latency);
  62. if (start >= minTime && start <= maxTime) {
  63. canvasDrawLoadEvent(ctx, y_offset, event, minTime, maxTime);
  64. y_offset += 20;
  65. }
  66. }
  67. }
  68. function canvasVideoEventUpdate(canvas, minTime, maxTime, events) {
  69. var event;
  70. var start;
  71. var ctx = canvas.getContext('2d');
  72. for (var i = 0, y_offset = 20; i < events.length; i++) {
  73. event = events[i];
  74. start = event.time;
  75. // end = event.time;
  76. if (start >= minTime && start <= maxTime) {
  77. y_offset += 20;
  78. }
  79. }
  80. canvas.height = y_offset;
  81. ctx.fillStyle = 'green';
  82. ctx.globalAlpha = 0.5;
  83. ctx.fillRect(0, 0, eventLeftMargin, canvas.height);
  84. ctx.fillRect(
  85. canvas.width - eventRightMargin,
  86. 0,
  87. eventRightMargin,
  88. canvas.height
  89. );
  90. ctx.globalAlpha = 1;
  91. // draw legend
  92. var x_offset = 5;
  93. ctx.font = '12px Arial';
  94. var legend = 'video event';
  95. ctx.fillStyle = 'black';
  96. ctx.fillText(legend, x_offset, 15);
  97. x_offset = eventLeftMargin + 5;
  98. legend = 'time';
  99. ctx.fillStyle = 'black';
  100. ctx.fillText(legend, x_offset, 15);
  101. x_offset += ctx.measureText(legend).width + 5;
  102. legend = '[duration]';
  103. ctx.fillStyle = 'blue';
  104. ctx.fillText(legend, x_offset, 15);
  105. for (i = 0, y_offset = 20; i < events.length; i++) {
  106. event = events[i];
  107. start = Math.round(event.time);
  108. // end = Math.round(event.time);
  109. if (start >= minTime && start <= maxTime) {
  110. canvasDrawVideoEvent(ctx, y_offset, event, minTime, maxTime);
  111. y_offset += 20;
  112. }
  113. }
  114. }
  115. function canvasBufferWindowUpdate(canvas, minTime, maxTime, focusTime, events) {
  116. var ctx = canvas.getContext('2d');
  117. var minTimeBuffer;
  118. var minTimePos;
  119. var focusTimeBuffer;
  120. var focusTimePos;
  121. var bufferChartStart = eventLeftMargin;
  122. var bufferChartWidth = ctx.canvas.width - eventLeftMargin - eventRightMargin;
  123. ctx.clearRect(0, 0, canvas.width, canvas.height);
  124. if (events.length === 0) {
  125. return;
  126. }
  127. ctx.fillStyle = 'green';
  128. ctx.globalAlpha = 0.5;
  129. ctx.fillRect(0, 0, eventLeftMargin, canvas.height);
  130. ctx.globalAlpha = 1;
  131. // draw legend
  132. var x_offset = 5;
  133. var y_offset = 0;
  134. ctx.font = '15px Arial';
  135. var maxBuffer = 0;
  136. var firstEventIdx = -1;
  137. var focusEventIdx = -1;
  138. var event;
  139. for (var i = 0; i < events.length; i++) {
  140. event = events[i];
  141. maxBuffer = Math.max(maxBuffer, event.buffer + event.pos);
  142. if (firstEventIdx === -1 && event.time >= minTime) {
  143. firstEventIdx = Math.max(0, i - 1);
  144. }
  145. if (focusEventIdx === -1 && event.time >= focusTime) {
  146. focusEventIdx = Math.max(0, i - 1);
  147. }
  148. }
  149. // compute position and buffer length at pos minTime using linear approximation
  150. if (firstEventIdx + 1 < events.length) {
  151. minTimePos =
  152. events[firstEventIdx].pos +
  153. ((minTime - events[firstEventIdx].time) *
  154. (events[firstEventIdx + 1].pos - events[firstEventIdx].pos)) /
  155. (events[firstEventIdx + 1].time - events[firstEventIdx].time);
  156. minTimeBuffer =
  157. minTimePos +
  158. events[firstEventIdx].buffer +
  159. ((minTime - events[firstEventIdx].time) *
  160. (events[firstEventIdx + 1].buffer - events[firstEventIdx].buffer)) /
  161. (events[firstEventIdx + 1].time - events[firstEventIdx].time);
  162. } else {
  163. minTimeBuffer = 0;
  164. minTimePos = 0;
  165. }
  166. // compute position and buffer length at pos focusTime using linear approximation
  167. if (focusEventIdx + 1 < events.length) {
  168. focusTimePos =
  169. events[focusEventIdx].pos +
  170. ((focusTime - events[focusEventIdx].time) *
  171. (events[focusEventIdx + 1].pos - events[focusEventIdx].pos)) /
  172. (events[focusEventIdx + 1].time - events[focusEventIdx].time);
  173. focusTimeBuffer =
  174. events[focusEventIdx].buffer +
  175. ((focusTime - events[focusEventIdx].time) *
  176. (events[focusEventIdx + 1].buffer - events[focusEventIdx].buffer)) /
  177. (events[focusEventIdx + 1].time - events[focusEventIdx].time);
  178. } else {
  179. focusTimePos = 0;
  180. focusTimeBuffer = 0;
  181. }
  182. maxBuffer *= 1.1;
  183. y_offset += 15;
  184. var legend = 'play pos/buffer zoomed';
  185. ctx.fillStyle = 'black';
  186. ctx.fillText(legend, x_offset, y_offset);
  187. y_offset += 15;
  188. legend = '[' + minTime + ',' + maxTime + ']';
  189. ctx.fillText(legend, x_offset, y_offset);
  190. y_offset += 15;
  191. legend = 'focus time:' + focusTime + ' ms';
  192. ctx.fillText(legend, x_offset, y_offset);
  193. y_offset += 15;
  194. legend = 'focus position:' + Math.round(focusTimePos) + ' ms';
  195. ctx.fillText(legend, x_offset, y_offset);
  196. y_offset += 15;
  197. legend = 'focus buffer:' + Math.round(focusTimeBuffer) + ' ms';
  198. ctx.fillText(legend, x_offset, y_offset);
  199. ctx.fillStyle = 'blue';
  200. ctx.beginPath();
  201. ctx.moveTo(bufferChartStart, ctx.canvas.height);
  202. ctx.lineTo(
  203. bufferChartStart,
  204. ctx.canvas.height * (1 - minTimeBuffer / maxBuffer)
  205. );
  206. for (var j = firstEventIdx + 1; j < events.length; j++) {
  207. event = events[j];
  208. x_offset =
  209. bufferChartStart +
  210. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  211. y_offset = ctx.canvas.height * (1 - (event.buffer + event.pos) / maxBuffer);
  212. ctx.lineTo(x_offset, y_offset);
  213. }
  214. ctx.lineTo(x_offset, canvas.height);
  215. ctx.fill();
  216. ctx.fillStyle = 'brown';
  217. ctx.beginPath();
  218. ctx.moveTo(bufferChartStart, ctx.canvas.height);
  219. ctx.lineTo(
  220. bufferChartStart,
  221. ctx.canvas.height * (1 - minTimePos / maxBuffer)
  222. );
  223. for (var k = firstEventIdx + 1; k < events.length; k++) {
  224. event = events[k];
  225. x_offset =
  226. bufferChartStart +
  227. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  228. y_offset = ctx.canvas.height * (1 - event.pos / maxBuffer);
  229. ctx.lineTo(x_offset, y_offset);
  230. }
  231. ctx.lineTo(x_offset, canvas.height);
  232. ctx.fill();
  233. ctx.fillStyle = 'white';
  234. ctx.fillRect(
  235. canvas.width - eventRightMargin,
  236. 0,
  237. eventRightMargin,
  238. canvas.height
  239. );
  240. ctx.fillStyle = 'green';
  241. ctx.globalAlpha = 0.5;
  242. ctx.fillRect(
  243. canvas.width - eventRightMargin,
  244. 0,
  245. eventRightMargin,
  246. canvas.height
  247. );
  248. ctx.globalAlpha = 1;
  249. ctx.fillStyle = 'black';
  250. x_offset =
  251. bufferChartStart +
  252. (bufferChartWidth * (focusTime - minTime)) / (maxTime - minTime);
  253. ctx.moveTo(x_offset, ctx.canvas.height);
  254. y_offset =
  255. ctx.canvas.height * (1 - (focusTimePos + focusTimeBuffer) / maxBuffer);
  256. ctx.lineTo(x_offset, y_offset);
  257. ctx.stroke();
  258. }
  259. function canvasBufferTimeRangeUpdate(
  260. canvas,
  261. minTime,
  262. maxTime,
  263. windowMinTime,
  264. windowMaxTime,
  265. events
  266. ) {
  267. var ctx = canvas.getContext('2d');
  268. var bufferChartStart = eventLeftMargin;
  269. var bufferChartWidth = ctx.canvas.width - eventLeftMargin - eventRightMargin;
  270. var x_offset = 0;
  271. var y_offset = 0;
  272. var event;
  273. ctx.clearRect(0, 0, canvas.width, canvas.height);
  274. ctx.fillStyle = 'green';
  275. ctx.globalAlpha = 0.5;
  276. ctx.fillRect(0, 0, eventLeftMargin, canvas.height);
  277. ctx.fillRect(
  278. canvas.width - eventRightMargin,
  279. 0,
  280. eventRightMargin,
  281. canvas.height
  282. );
  283. ctx.globalAlpha = 1;
  284. x_offset = 5;
  285. y_offset = 15;
  286. var legend = 'play pos/buffer';
  287. ctx.fillStyle = 'black';
  288. ctx.font = '15px Arial';
  289. ctx.fillText(legend, x_offset, y_offset);
  290. if (events.length === 0) {
  291. return;
  292. }
  293. var maxBuffer = 0;
  294. for (var i = 0; i < events.length; i++) {
  295. maxBuffer = Math.max(maxBuffer, events[i].buffer + events[i].pos);
  296. }
  297. y_offset += 15;
  298. legend = 'last pos:' + events[events.length - 1].pos + ' ms';
  299. ctx.fillText(legend, x_offset, y_offset);
  300. y_offset += 15;
  301. legend = 'last buffer:' + events[events.length - 1].buffer + ' ms';
  302. ctx.fillText(legend, x_offset, y_offset);
  303. y_offset += 15;
  304. legend = 'max buffer:' + maxBuffer + ' ms';
  305. ctx.fillText(legend, x_offset, y_offset);
  306. y_offset += 15;
  307. legend = 'nb samples:' + events.length;
  308. ctx.fillText(legend, x_offset, y_offset);
  309. maxBuffer *= 1.1;
  310. ctx.fillStyle = 'blue';
  311. ctx.beginPath();
  312. ctx.moveTo(bufferChartStart, ctx.canvas.height);
  313. for (var j = 0; j < events.length; j++) {
  314. event = events[j];
  315. x_offset =
  316. bufferChartStart +
  317. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  318. y_offset = ctx.canvas.height * (1 - (event.buffer + event.pos) / maxBuffer);
  319. ctx.lineTo(x_offset, y_offset);
  320. }
  321. ctx.lineTo(x_offset, canvas.height);
  322. ctx.fill();
  323. ctx.fillStyle = 'brown';
  324. ctx.beginPath();
  325. ctx.moveTo(bufferChartStart, ctx.canvas.height);
  326. for (var k = 0; k < events.length; k++) {
  327. event = events[k];
  328. x_offset =
  329. bufferChartStart +
  330. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  331. y_offset = ctx.canvas.height * (1 - event.pos / maxBuffer);
  332. ctx.lineTo(x_offset, y_offset);
  333. }
  334. ctx.lineTo(x_offset, canvas.height);
  335. ctx.fill();
  336. ctx.globalAlpha = 0.7;
  337. ctx.fillStyle = 'grey';
  338. var x_start = bufferChartStart;
  339. var x_w =
  340. (bufferChartWidth * (windowMinTime - minTime)) / (maxTime - minTime);
  341. ctx.fillRect(x_start, 0, x_w, canvas.height);
  342. x_start =
  343. bufferChartStart +
  344. (bufferChartWidth * (windowMaxTime - minTime)) / (maxTime - minTime);
  345. x_w = canvas.width - x_start - eventRightMargin;
  346. ctx.fillRect(x_start, 0, x_w, canvas.height);
  347. ctx.globalAlpha = 1;
  348. }
  349. function canvasBitrateEventUpdate(
  350. canvas,
  351. minTime,
  352. maxTime,
  353. windowMinTime,
  354. windowMaxTime,
  355. levelEvents,
  356. bitrateEvents
  357. ) {
  358. var ctx = canvas.getContext('2d');
  359. var bufferChartStart = eventLeftMargin;
  360. var bufferChartWidth = ctx.canvas.width - eventLeftMargin - eventRightMargin;
  361. var x_offset = 0;
  362. var y_offset = 0;
  363. var event;
  364. var maxLevel;
  365. var minLevel;
  366. var sumLevel;
  367. var maxBitrate;
  368. var minBitrate;
  369. var sumDuration;
  370. ctx.clearRect(0, 0, canvas.width, canvas.height);
  371. if (levelEvents.length === 0 || bitrateEvents.length === 0) {
  372. return;
  373. }
  374. maxBitrate = minBitrate = bitrateEvents[0].bitrate;
  375. sumLevel = sumDuration = 0;
  376. for (var i = 0; i < bitrateEvents.length; i++) {
  377. sumLevel += bitrateEvents[i].duration * bitrateEvents[i].level;
  378. sumDuration += bitrateEvents[i].duration;
  379. maxBitrate = Math.max(maxBitrate, bitrateEvents[i].bitrate);
  380. minBitrate = Math.min(minBitrate, bitrateEvents[i].bitrate);
  381. }
  382. maxLevel = minLevel = levelEvents[0].id;
  383. for (var j = 0; j < levelEvents.length; j++) {
  384. maxLevel = Math.max(maxLevel, levelEvents[j].id);
  385. minLevel = Math.min(minLevel, levelEvents[j].id);
  386. }
  387. ctx.fillStyle = 'green';
  388. ctx.globalAlpha = 0.5;
  389. ctx.fillRect(0, 0, eventLeftMargin, canvas.height);
  390. ctx.fillRect(
  391. canvas.width - eventRightMargin,
  392. 0,
  393. eventRightMargin,
  394. canvas.height
  395. );
  396. ctx.globalAlpha = 1;
  397. x_offset = 5;
  398. y_offset = 0;
  399. ctx.fillStyle = 'black';
  400. ctx.font = '15px Arial';
  401. y_offset += 15;
  402. var legend =
  403. 'last bitrate:' +
  404. (bitrateEvents[bitrateEvents.length - 1].bitrate / 1000).toFixed(2) +
  405. 'Mb/s';
  406. ctx.fillText(legend, x_offset, y_offset);
  407. y_offset += 15;
  408. legend = 'min bitrate:' + (minBitrate / 1000).toFixed(2) + 'Mb/s';
  409. ctx.fillText(legend, x_offset, y_offset);
  410. y_offset += 15;
  411. legend = 'max bitrate:' + (maxBitrate / 1000).toFixed(2) + 'Mb/s';
  412. ctx.fillText(legend, x_offset, y_offset);
  413. y_offset += 15;
  414. legend =
  415. 'min/last/max level:' +
  416. minLevel +
  417. '/' +
  418. levelEvents[levelEvents.length - 1].id +
  419. '/' +
  420. maxLevel;
  421. ctx.fillText(legend, x_offset, y_offset);
  422. y_offset += 15;
  423. legend = 'nb level switch:' + (levelEvents.length - 1);
  424. ctx.fillText(legend, x_offset, y_offset);
  425. y_offset += 15;
  426. legend = 'average level:' + (sumLevel / sumDuration).toFixed(2);
  427. ctx.fillText(legend, x_offset, y_offset);
  428. maxBitrate *= 1.1;
  429. ctx.strokeStyle = 'blue';
  430. ctx.beginPath();
  431. ctx.moveTo(bufferChartStart, ctx.canvas.height);
  432. for (var k = 0; k < bitrateEvents.length; k++) {
  433. event = bitrateEvents[k];
  434. x_offset =
  435. bufferChartStart +
  436. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  437. y_offset = ctx.canvas.height * (1 - event.bitrate / maxBitrate);
  438. ctx.lineTo(x_offset, y_offset);
  439. }
  440. ctx.lineTo(bufferChartStart + bufferChartWidth, y_offset);
  441. ctx.stroke();
  442. ctx.strokeStyle = 'black';
  443. ctx.beginPath();
  444. x_offset = bufferChartStart;
  445. y_offset = ctx.canvas.height;
  446. ctx.moveTo(x_offset, y_offset);
  447. for (var l = 0; l < levelEvents.length; l++) {
  448. event = levelEvents[l];
  449. x_offset =
  450. bufferChartStart +
  451. (bufferChartWidth * (event.time - minTime)) / (maxTime - minTime);
  452. ctx.lineTo(x_offset, y_offset);
  453. y_offset = ctx.canvas.height * (1 - event.bitrate / maxBitrate);
  454. ctx.lineTo(x_offset, y_offset);
  455. }
  456. ctx.lineTo(bufferChartStart + bufferChartWidth, y_offset);
  457. ctx.stroke();
  458. ctx.globalAlpha = 0.7;
  459. ctx.fillStyle = 'grey';
  460. var x_start = bufferChartStart;
  461. var x_w =
  462. (bufferChartWidth * (windowMinTime - minTime)) / (maxTime - minTime);
  463. ctx.fillRect(x_start, 0, x_w, canvas.height);
  464. x_start =
  465. bufferChartStart +
  466. (bufferChartWidth * (windowMaxTime - minTime)) / (maxTime - minTime);
  467. x_w = canvas.width - x_start - eventRightMargin;
  468. ctx.fillRect(x_start, 0, x_w, canvas.height);
  469. ctx.globalAlpha = 1;
  470. }
  471. function canvasDrawLoadEvent(ctx, yoffset, event, minTime, maxTime) {
  472. var legend;
  473. var offset;
  474. var x_start;
  475. var x_w;
  476. var networkChartStart = eventLeftMargin;
  477. var networkChartWidth = ctx.canvas.width - eventLeftMargin - eventRightMargin;
  478. var tend = Math.round(event.time + event.duration + event.latency);
  479. // draw start
  480. ctx.fillStyle = 'black';
  481. ctx.font = '12px Arial';
  482. legend = Math.round(event.time);
  483. offset = ctx.measureText(legend).width + 5;
  484. x_start =
  485. networkChartStart -
  486. offset +
  487. (networkChartWidth * (event.time - minTime)) / (maxTime - minTime);
  488. ctx.fillText(legend, x_start, yoffset + 12);
  489. // draw latency rectangle
  490. ctx.fillStyle = 'orange';
  491. x_start =
  492. networkChartStart +
  493. (networkChartWidth * (event.time - minTime)) / (maxTime - minTime);
  494. x_w = (networkChartWidth * event.latency) / (maxTime - minTime);
  495. ctx.fillRect(x_start, yoffset, x_w, 15);
  496. // draw download rectangle
  497. ctx.fillStyle = 'green';
  498. x_start =
  499. networkChartStart +
  500. (networkChartWidth * (event.time + event.latency - minTime)) /
  501. (maxTime - minTime);
  502. x_w = (networkChartWidth * event.load) / (maxTime - minTime);
  503. ctx.fillRect(x_start, yoffset, x_w, 15);
  504. if (event.parsing) {
  505. // draw parsing rectangle
  506. ctx.fillStyle = 'blue';
  507. x_start =
  508. networkChartStart +
  509. (networkChartWidth *
  510. (event.time + event.latency + event.load - minTime)) /
  511. (maxTime - minTime);
  512. x_w = (networkChartWidth * event.parsing) / (maxTime - minTime);
  513. ctx.fillRect(x_start, yoffset, x_w, 15);
  514. if (event.buffer) {
  515. // draw buffering rectangle
  516. ctx.fillStyle = 'red';
  517. x_start =
  518. networkChartStart +
  519. (networkChartWidth *
  520. (event.time + event.latency + event.load + event.parsing - minTime)) /
  521. (maxTime - minTime);
  522. x_w = (networkChartWidth * event.buffer) / (maxTime - minTime);
  523. ctx.fillRect(x_start, yoffset, x_w, 15);
  524. }
  525. }
  526. // draw end time
  527. ctx.fillStyle = 'black';
  528. ctx.font = '12px Arial';
  529. legend = tend;
  530. x_start += x_w + 5;
  531. ctx.fillText(legend, x_start, yoffset + 12);
  532. x_start += ctx.measureText(legend).width + 5;
  533. legend = '[' + Math.round(event.latency);
  534. ctx.fillStyle = 'orange';
  535. ctx.fillText(legend, x_start, yoffset + 12);
  536. x_start += ctx.measureText(legend).width + 5;
  537. legend = Math.round(event.load);
  538. if (!event.parsing) {
  539. legend += ']';
  540. }
  541. ctx.fillStyle = 'green';
  542. ctx.fillText(legend, x_start, yoffset + 12);
  543. x_start += ctx.measureText(legend).width + 5;
  544. if (event.parsing) {
  545. legend = Math.round(event.parsing);
  546. if (!event.buffer) {
  547. legend += ']';
  548. }
  549. ctx.fillStyle = 'blue';
  550. ctx.fillText(legend, x_start, yoffset + 12);
  551. x_start += ctx.measureText(legend).width + 5;
  552. if (event.buffer) {
  553. legend = Math.round(event.buffer) + ']';
  554. ctx.fillStyle = 'red';
  555. ctx.fillText(legend, x_start, yoffset + 12);
  556. x_start += ctx.measureText(legend).width + 5;
  557. }
  558. }
  559. if (event.size) {
  560. if (event.size > 1000 * 1000) {
  561. legend = (event.size / 1000000).toFixed(1) + 'MB';
  562. } else {
  563. legend = Math.round(event.size / 1000) + 'kB';
  564. }
  565. ctx.fillStyle = 'black';
  566. ctx.fillText(legend, x_start, yoffset + 12);
  567. x_start += ctx.measureText(legend).width + 5;
  568. }
  569. if (event.bw) {
  570. if (event.bw > 1000) {
  571. legend = (event.bw / 1000).toFixed(1) + 'Mbps';
  572. } else {
  573. legend = event.bw + ' kbps';
  574. }
  575. ctx.fillStyle = 'black';
  576. ctx.fillText(legend, x_start, yoffset + 12);
  577. x_start += ctx.measureText(legend).width + 5;
  578. }
  579. // draw event name
  580. ctx.fillStyle = 'black';
  581. ctx.font = '15px Arial';
  582. legend = event.type;
  583. if (event.id2 !== undefined) {
  584. legend += ' ' + event.id2;
  585. }
  586. if (event.id3 !== undefined) {
  587. legend += '/' + event.id3;
  588. }
  589. if (event.id !== undefined) {
  590. if (event.type.indexOf('fragment') !== -1) {
  591. legend += ' @';
  592. }
  593. legend += ' ' + event.id;
  594. }
  595. if (event.start !== undefined) {
  596. legend += ' [' + event.start + ',' + event.end + ']';
  597. }
  598. ctx.fillText(legend, 5, yoffset + 15);
  599. }
  600. function canvasDrawVideoEvent(ctx, yoffset, event, minTime, maxTime) {
  601. var legend;
  602. var offset;
  603. var x_start;
  604. var x_w;
  605. var networkChartStart = eventLeftMargin;
  606. var networkChartWidth = ctx.canvas.width - eventLeftMargin - eventRightMargin;
  607. // draw event name
  608. ctx.fillStyle = 'black';
  609. ctx.font = '15px Arial';
  610. legend = event.type;
  611. if (event.name !== undefined) {
  612. legend += ':' + event.name;
  613. }
  614. ctx.fillText(legend, 5, yoffset + 15);
  615. // draw start time
  616. ctx.fillStyle = 'black';
  617. ctx.font = '12px Arial';
  618. legend = Math.round(event.time);
  619. offset = ctx.measureText(legend).width + 5;
  620. x_start =
  621. networkChartStart -
  622. offset +
  623. (networkChartWidth * (event.time - minTime)) / (maxTime - minTime);
  624. ctx.fillText(legend, x_start, yoffset + 12);
  625. // draw event rectangle
  626. x_start =
  627. networkChartStart +
  628. (networkChartWidth * (event.time - minTime)) / (maxTime - minTime);
  629. if (event.duration) {
  630. x_w = (networkChartWidth * event.duration) / (maxTime - minTime);
  631. } else {
  632. x_w = 1;
  633. }
  634. ctx.fillRect(x_start, yoffset, x_w, 15);
  635. if (event.duration) {
  636. // draw end time
  637. ctx.fillStyle = 'black';
  638. ctx.font = '12px Arial';
  639. legend = Math.round(event.time + event.duration);
  640. x_start += x_w + 5;
  641. ctx.fillText(legend, x_start, yoffset + 12);
  642. x_start += ctx.measureText(legend).width + 5;
  643. legend = '[' + Math.round(event.duration) + ']';
  644. ctx.fillStyle = 'blue';
  645. ctx.fillText(legend, x_start, yoffset + 12);
  646. }
  647. }