index.html 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  6. <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=0,viewport-fit=cover">
  7. </head>
  8. <style>
  9. body {
  10. --spacing: .75rem;
  11. font-family: sans-serif;
  12. line-height: 1.5;
  13. text-align: center;
  14. margin: .75rem;
  15. padding-bottom: 2rem;
  16. color: hsl(269,19%,30%);
  17. background-color: hsla(32,100%,85%,.35);
  18. background-image: url("data:image/svg+xml;charset=utf8,%3Csvg width='100%25' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.4'/%3E%3C/filter%3E%3C/defs%3E%3C!-- %3Cpath filter='url(%23a)' opacity='.3' d='M0 0h1200v256H0z'/%3E--%3E%3Crect filter='url(%23a)' opacity='.3' width='100%25' height='100%25'/%3E%3C/svg%3E");
  19. }
  20. @media (min-width: 48em) {
  21. body {--spacing: 1rem;}
  22. }
  23. body * {box-sizing: border-box;}
  24. h1, h2, h3 {font-weight:100;}
  25. h1 {margin: 1em 0 .5em;}
  26. .group {
  27. border: 1px solid #fff;
  28. background-color: rgba(255,255,255,.25);
  29. padding: .5rem 1rem;
  30. margin: 1rem auto;
  31. }
  32. .url {
  33. display: flex;
  34. width: 100%;
  35. margin: 1rem auto;
  36. }
  37. [class*="_label"] {
  38. position: relative;
  39. white-space: nowrap;
  40. margin-right: .5em;
  41. min-width: 4em;
  42. }
  43. [class*="_label"] > span {
  44. display: block;
  45. position: relative;
  46. top: 50%;
  47. transform: translatey(-50%);
  48. }
  49. [class*="_input"] {
  50. display: inline-block;
  51. line-height: 1;
  52. width: 100%;
  53. margin: 0;
  54. padding: .25rem .5rem;
  55. font: inherit;
  56. border: 1px solid #fff;
  57. background-color: rgba(255,255,255,.5);
  58. }
  59. .upload {
  60. display: flex;
  61. width: 100%;
  62. margin: 1rem auto;
  63. }
  64. .player_audio {
  65. width: 100%;
  66. }
  67. .player_display {
  68. font-size: 1.25rem;
  69. }
  70. .tempo {
  71. display: flex;
  72. width: 100%;
  73. margin: 1rem auto;
  74. }
  75. .tempo_display {
  76. font-weight: 700;
  77. min-width: 3em;
  78. margin-left: .5em;
  79. }
  80. </style>
  81. <body>
  82. <main>
  83. <div class=group>
  84. <div class=upload>
  85. <label class=upload_label for=upload_input><span>上传</span></label>
  86. <input id=upload_input class=upload_input type=file accept="audio/*">
  87. </div>
  88. </div>
  89. <div class=group>
  90. <div class=player>
  91. <h3 class=player_display>SJE40W8.mp3</h3>
  92. <audio class=player_audio controls src="./SJE40W8.mp3">
  93. <track id=player-chords kind=captions srclang=en>
  94. </audio>
  95. </div>
  96. <div class=tempo>
  97. <label class=tempo_label for=tempo_input>速度</label>
  98. <input class=tempo_input id=tempo_input type=range value=1 min=0.25 max=2.5 step=0.01>
  99. <span class=tempo_display></span>
  100. </div>
  101. </div>
  102. </main>
  103. <script>
  104. const player = document.querySelector('.player_audio');
  105. const playerDisplay = document.querySelector('.player_display');
  106. const changeTempo = function () {
  107. player.playbackRate = tempoInput.value;
  108. tempoDisplay.textContent = tempoInput.value;
  109. };
  110. const changeSongURL = function (e) {
  111. player.src = urlInput.value;
  112. let filename = player.src.split('\\').pop().split('/').pop();
  113. playerDisplay.textContent = filename;
  114. }
  115. const changeSongFile = function (e) {
  116. const target = e.currentTarget;
  117. const file = target.files[0];
  118. let reader;
  119. if (target.files && file) {
  120. reader = new FileReader();
  121. reader.onload = function (e) {
  122. player.setAttribute('src', e.target.result);
  123. playerDisplay.textContent = file.name;
  124. // player.play(); // auto play on load
  125. }
  126. reader.readAsDataURL(file);
  127. }
  128. };
  129. // Get the song from:
  130. // const urlInput = document.getElementById('url_input');
  131. // urlInput.addEventListener("change", changeSongURL, false);
  132. // Or upload an MP3:
  133. const uploadInput = document.getElementById('upload_input');
  134. uploadInput.addEventListener('change', changeSongFile, false);
  135. // Playback tempo
  136. const tempoInput = document.getElementById('tempo_input');
  137. tempoInput.addEventListener("change", changeTempo, false);
  138. const tempoDisplay = document.querySelector('.tempo_display');
  139. tempoDisplay.textContent = tempoInput.value;
  140. // Chords from:
  141. // const vtt = document.getElementById('url_input').value.replace('.mp3', '.vtt');
  142. // const player_chords = document.getElementById('player-chords');
  143. // player_chords.src = vtt;
  144. // player.src = urlInput.value;
  145. // changeSongURL();
  146. changeTempo();
  147. </script>
  148. </body>
  149. </html>