chart.html 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>ISP Speed Chart</title>
  5. <script src="chartjs/Chart.min.js"></script>
  6. <script src="chartjs/utils.js"></script>
  7. <style>
  8. canvas {
  9. -moz-user-select: none;
  10. -webkit-user-select: none;
  11. -ms-user-select: none;
  12. position: relative;
  13. flex-grow: 1;
  14. min-height: 0;
  15. width: 100%;
  16. height:100%;
  17. }
  18. div {
  19. width:100%;
  20. height:100%;
  21. }
  22. body {
  23. background: #ffffff;
  24. color: #000000;
  25. transition: background 0.3s, color 0.3s;
  26. }
  27. /* 深色模式适配 */
  28. @media (prefers-color-scheme: dark) {
  29. body {
  30. background: #121212;
  31. color: #e0e0e0;
  32. }
  33. canvas {
  34. background: #1e1e1e;
  35. }
  36. }
  37. </style>
  38. </head>
  39. <body>
  40. <div>
  41. <canvas id="canvas"></canvas>
  42. </div>
  43. <script>
  44. var color = Chart.helpers.color;
  45. async function mainfunc() {
  46. var color = Chart.helpers.color;
  47. //console.log(color)
  48. var datareq = await fetch('backend/results-api.php');
  49. //console.log(datareq)
  50. var dataraw = await datareq.text();
  51. //console.log(dataraw)
  52. try {
  53. dataraw = JSON.parse(dataraw);
  54. } catch {
  55. alert("Can't get data");
  56. return 0;
  57. }
  58. data_sorted = {};
  59. for (const data of dataraw["data"]) {
  60. let data_isp = data["isp"].split(" ").length > 1 ? data["isp"].split(" ")[0] + " " + data["isp"].split(" ")[1] : data["isp"];
  61. if (data_isp in data_sorted) {
  62. data_sorted[data_isp] = data_sorted[data_isp].concat([data])
  63. } else {
  64. data_sorted[data_isp] = [data]
  65. }
  66. }
  67. let datasets = []
  68. for (const isp of Object.keys(data_sorted)) {
  69. let ispdata_chart = {
  70. label: isp,
  71. data: []
  72. }
  73. for (const ispdata of data_sorted[isp]) {
  74. let [t_h, t_m, t_s] = ispdata["created"].split(" ")[1].split(":");
  75. ispdata_chart["data"] = ispdata_chart["data"].concat([{
  76. x: t_h * 1.0 + t_m / 60 + t_s / 3600,
  77. y: ispdata["dspeed"],
  78. label: ispdata
  79. }]);
  80. }
  81. datasets = datasets.concat([ispdata_chart])
  82. }
  83. datasets = datasets.sort((a, b) => a["data"].length < b["data"].length ? 1 : -1);
  84. for (const [i, data] of datasets.entries()) {
  85. if (i === 0) {
  86. datasets[i]["borderColor"] = window.chartColors["red"];
  87. datasets[i]["backgroundColor"] = color(datasets[i]["borderColor"]).alpha(0.9).rgbString()
  88. } else if (i === 1) {
  89. datasets[i]["borderColor"] = "rgb(12, 176, 42)";
  90. datasets[i]["backgroundColor"] = color(datasets[i]["borderColor"]).alpha(0.9).rgbString()
  91. } else if (i === 2) {
  92. datasets[i]["borderColor"] = "rgb(2, 104, 219)";
  93. datasets[i]["backgroundColor"] = color(datasets[i]["borderColor"]).alpha(0.9).rgbString()
  94. }
  95. else{
  96. datasets[i]["borderColor"] = window.chartColors["gray"];;
  97. datasets[i]["backgroundColor"] = color(window.chartColors["gray"]).alpha(0.1).rgbString()
  98. }
  99. }
  100. console.log(datasets);
  101. scatterChartData = {
  102. datasets: datasets
  103. }
  104. var ctx = document.getElementById('canvas').getContext('2d');
  105. window.myScatter = Chart.Scatter(ctx, {
  106. data: scatterChartData,
  107. options: {
  108. title: {
  109. display: true,
  110. text: 'ISP Speed Chart'
  111. },
  112. tooltips: {
  113. mode: 'nearest',
  114. callbacks: {
  115. title: function(TooltipItem, data){
  116. // console.log(TooltipItem);
  117. // console.log(data);
  118. // console.log(data["datasets"][TooltipItem[0]["datasetIndex"]]["label"])
  119. return data["datasets"][TooltipItem[0]["datasetIndex"]]["label"]
  120. },
  121. label:function(TooltipItem, data){
  122. return data["datasets"][TooltipItem["datasetIndex"]]["data"][TooltipItem["index"]]["label"]["isp"];
  123. },
  124. footer: function(TooltipItem, data){
  125. // console.log(TooltipItem);
  126. // console.log(data);
  127. displaydata = data["datasets"][TooltipItem[0]["datasetIndex"]]["data"][TooltipItem[0]["index"]]["label"];
  128. showdict = {
  129. location: displaydata["addr"],
  130. Download: displaydata["dspeed"],
  131. Upload: displaydata["uspeed"],
  132. Ping: displaydata["ping"],
  133. Jitter: displaydata["jitter"],
  134. IP: displaydata["ip"],
  135. Time: displaydata["created"],
  136. // ISP: displaydata["isp"],
  137. };
  138. let showtext = ""
  139. for (const k of Object.keys(showdict)){
  140. showtext += k + ": " + showdict[k] + "\n";
  141. }
  142. return showtext
  143. },
  144. },
  145. footerFontStyle: 'normal'
  146. },
  147. scales: {
  148. yAxes: [{
  149. type: 'linear',
  150. position: 'bottom',
  151. ticks: {
  152. userCallback: function(tick) {
  153. return tick.toString() + 'Mbps';
  154. },
  155. },
  156. scaleLabel: {
  157. labelString: 'Speed',
  158. display: true,
  159. }
  160. }],
  161. xAxes: [{
  162. type: 'linear',
  163. ticks: {
  164. userCallback: function(tick) {
  165. return tick.toString() + ':00';
  166. },
  167. beginAtZero: true,
  168. stepSize: 3,
  169. max: 24
  170. },
  171. scaleLabel: {
  172. labelString: 'Time',
  173. display: true
  174. }
  175. }]
  176. },
  177. responsive: true,
  178. maintainAspectRatio: false
  179. }
  180. });
  181. }
  182. window.onload = function() {
  183. mainfunc();
  184. };
  185. </script>
  186. </body>
  187. </html>