index.htm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. <title>Highcharts Example</title>
  7. <style type="text/css">
  8. #container {
  9. min-width: 320px;
  10. max-width: 900px;
  11. height: 500px;
  12. margin: 0 auto
  13. }
  14. #controls {
  15. margin: 0 auto;
  16. text-align: center;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <script src="../../code/highcharts.js"></script>
  22. <script src="../../code/modules/data.js"></script>
  23. <script src="../../code/modules/sonification.js"></script>
  24. <div id="container"></div>
  25. <div id="controls" style="">
  26. <button id="play">Play</button>
  27. <button id="pause">Pause</button>
  28. <button id="rewind">Rewind</button>
  29. <input type="range" id="speed" name="Speed"
  30. min="0.5" max="2" value="1" step="0.05">
  31. <label for="speed">Speed</label>
  32. </div>
  33. <pre id="csv_data" style="display:none">2018-01-07,61,9,61,15.85714286
  34. 2018-01-14,66,20,61,33.85714286
  35. 2018-01-21,56,41,60,31.85714286
  36. 2018-01-28,61,46,58,39.28571429
  37. 2018-02-04,63,35,65,32.14285714
  38. 2018-02-11,61,47,61,35.85714286
  39. 2018-02-18,61,37,62,40.42857143
  40. 2018-02-25,55,44,54,45
  41. 2018-03-04,57,41,56,43.42857143
  42. 2018-03-11,62,38,61,36.57142857
  43. 2018-03-18,57,36,60,36.57142857
  44. 2018-03-25,59,40,61,38.14285714
  45. 2018-04-01,60,48,60,43.28571429
  46. 2018-04-08,64,38,62,41.14285714
  47. 2018-04-15,68,43,66,45.85714286
  48. 2018-04-22,64,51,61,46
  49. 2018-04-29,62,54,62,53.28571429
  50. 2018-05-06,67,60,62,62.57142857
  51. 2018-05-13,63,53,62,58.42857143
  52. 2018-05-20,62,67,63,60.14285714
  53. 2018-05-27,63,65,63,67.71428571
  54. 2018-06-03,67,63,65,65.14285714
  55. 2018-06-10,68,68,66,64
  56. 2018-06-17,65,74,67,68.57142857
  57. 2018-06-24,65,69,66,71.42857143
  58. 2018-07-01,66,82,67,75.14285714
  59. 2018-07-08,78,69,72,76.57142857
  60. 2018-07-15,74,75,74,75.14285714
  61. 2018-07-22,76,73,73,74.85714286
  62. 2018-07-29,76,77,75,76.57142857
  63. 2018-08-05,76,81,77,77.42857143
  64. 2018-08-12,80,76,81,79
  65. 2018-08-19,76,71,76,77
  66. 2018-08-26,74,73,75,73
  67. 2018-09-02,71,72,74,78.28571429
  68. 2018-09-09,70,61,72,75
  69. 2018-09-16,74,72,72,69.71428571
  70. 2018-09-23,71,63,71,70.42857143
  71. 2018-09-30,71,63,69,65.71428571
  72. 2018-10-07,68,71,71,68.14285714
  73. 2018-10-14,68,53,68,64
  74. </pre>
  75. <script type="text/javascript">
  76. // Sonification options
  77. var sdInstruments = [{
  78. instrument: 'sineMajor',
  79. instrumentMapping: {
  80. duration: 200,
  81. frequency: 'y',
  82. volume: 0.7,
  83. pan: -1
  84. },
  85. instrumentOptions: {
  86. minFrequency: 220,
  87. maxFrequency: 1900
  88. }
  89. }],
  90. nyInstruments = [{
  91. instrument: 'triangleMajor',
  92. instrumentMapping: {
  93. duration: 200,
  94. frequency: 'y',
  95. volume: 0.6,
  96. pan: 1
  97. },
  98. instrumentOptions: {
  99. minFrequency: 220,
  100. maxFrequency: 1900
  101. }
  102. }];
  103. // Point of interest options
  104. var poiTime = Date.UTC(2018, 4, 6),
  105. poiEarcon = {
  106. // Define the earcon we want to play for the point of interest
  107. earcon: new Highcharts.sonification.Earcon({
  108. instruments: [{
  109. instrument: 'squareMajor',
  110. playOptions: {
  111. // Play a quick rising frequency
  112. frequency: function (time) {
  113. return time * 1760 + 440;
  114. },
  115. volume: 0.1,
  116. duration: 200
  117. }
  118. }]
  119. }),
  120. // Play this earcon if we hit the point of interest
  121. condition: function (point) {
  122. return point.x === poiTime;
  123. }
  124. };
  125. // Create the chart
  126. var chart = Highcharts.chart('container', {
  127. chart: {
  128. type: 'spline'
  129. },
  130. title: {
  131. text: 'Play chart as sound'
  132. },
  133. subtitle: {
  134. text: 'Weekly temperature averages'
  135. },
  136. yAxis: {
  137. title: {
  138. text: 'Temperature (°F)'
  139. }
  140. },
  141. xAxis: {
  142. type: 'datetime',
  143. plotLines: [{
  144. value: poiTime,
  145. dashStyle: 'dash',
  146. width: 1,
  147. color: '#d33'
  148. }]
  149. },
  150. tooltip: {
  151. split: true,
  152. valueDecimals: 0,
  153. valueSuffix: '°F'
  154. },
  155. plotOptions: {
  156. series: {
  157. marker: {
  158. enabled: false
  159. },
  160. cursor: 'pointer',
  161. // Sonify points on click
  162. point: {
  163. events: {
  164. click: function () {
  165. // Sonify all points at this x value
  166. var targetX = this.x,
  167. chart = this.series.chart;
  168. chart.series.forEach(function (series) {
  169. // Map instruments to the options for this series
  170. var instruments = series.options.id === 'sd' ?
  171. sdInstruments : nyInstruments;
  172. // See if we have a point with the targetX
  173. series.points.some(function (point) {
  174. if (point.x === targetX) {
  175. point.sonify({
  176. instruments: instruments
  177. });
  178. return true;
  179. }
  180. return false;
  181. });
  182. });
  183. }
  184. }
  185. }
  186. }
  187. },
  188. // Data source: https://www.ncdc.noaa.gov
  189. data: {
  190. csv: document.getElementById('csv_data').innerHTML,
  191. firstRowAsNames: false,
  192. parsed: function (columns) {
  193. columns.splice(1, 2); // Remove the non-average columns
  194. }
  195. },
  196. series: [{
  197. name: 'San Diego',
  198. id: 'sd',
  199. color: '#f4b042'
  200. }, {
  201. name: 'New York',
  202. id: 'ny',
  203. color: '#41aff4'
  204. }]
  205. });
  206. // Utility function that highlights a point
  207. function highlightPoint(event, point) {
  208. var chart = point.series.chart,
  209. hasVisibleSeries = chart.series.some(function (series) {
  210. return series.visible;
  211. });
  212. if (!point.isNull && hasVisibleSeries) {
  213. point.onMouseOver(); // Show the hover marker and tooltip
  214. } else {
  215. if (chart.tooltip) {
  216. chart.tooltip.hide(0);
  217. }
  218. }
  219. }
  220. // On speed change we reset the sonification
  221. document.getElementById('speed').onchange = function () {
  222. chart.cancelSonify();
  223. };
  224. // Add sonification button handlers
  225. document.getElementById('play').onclick = function () {
  226. if (!chart.sonification.timeline || chart.sonification.timeline.atStart()) {
  227. chart.sonify({
  228. duration: 5000 / document.getElementById('speed').value,
  229. order: 'simultaneous',
  230. pointPlayTime: 'x',
  231. seriesOptions: [{
  232. id: 'sd',
  233. instruments: sdInstruments,
  234. onPointStart: highlightPoint,
  235. // Play earcon at point of interest
  236. earcons: [poiEarcon]
  237. }, {
  238. id: 'ny',
  239. instruments: nyInstruments,
  240. onPointStart: highlightPoint
  241. }],
  242. // Delete timeline on end
  243. onEnd: function () {
  244. if (chart.sonification.timeline) {
  245. delete chart.sonification.timeline;
  246. }
  247. }
  248. });
  249. } else {
  250. chart.resumeSonify();
  251. }
  252. };
  253. document.getElementById('pause').onclick = function () {
  254. chart.pauseSonify();
  255. };
  256. document.getElementById('rewind').onclick = function () {
  257. chart.rewindSonify();
  258. };
  259. </script>
  260. </body>
  261. </html>