hivecorp commited on
Commit
91915a2
·
verified ·
1 Parent(s): e608769

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +108 -9
index.html CHANGED
@@ -49,15 +49,39 @@
49
  border-radius: 5px;
50
  cursor: pointer;
51
  transition: background-color 0.3s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
- .play-button:hover {
55
- background-color: #2980b9;
 
 
56
  }
57
 
58
  audio {
59
  display: none;
60
  }
 
 
 
 
 
 
61
  </style>
62
  </head>
63
  <body>
@@ -78,6 +102,10 @@
78
 
79
  const container = document.getElementById('audioContainer');
80
  let currentAudio = null;
 
 
 
 
81
 
82
  voices.forEach(voice => {
83
  const audioElement = document.createElement('audio');
@@ -90,35 +118,106 @@
90
  const nameSpan = document.createElement('span');
91
  nameSpan.textContent = voice.name;
92
 
 
 
 
93
  const playButton = document.createElement('button');
94
  playButton.className = 'play-button';
95
- playButton.textContent = 'Play';
96
- playButton.onclick = () => toggleAudio(audioElement, playButton);
 
 
 
 
97
 
98
  itemDiv.appendChild(nameSpan);
 
99
  itemDiv.appendChild(playButton);
100
  container.appendChild(itemDiv);
101
  container.appendChild(audioElement);
102
  });
103
 
104
- function toggleAudio(audioElement, button) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  if (currentAudio && currentAudio !== audioElement) {
106
  currentAudio.pause();
107
- currentAudio.previousElementSibling.textContent = 'Play';
 
108
  }
109
 
110
  if (audioElement.paused) {
 
 
 
111
  audioElement.play();
112
- button.textContent = 'Pause';
 
 
113
  currentAudio = audioElement;
114
  } else {
115
  audioElement.pause();
116
- button.textContent = 'Play';
 
 
117
  currentAudio = null;
118
  }
119
 
120
  audioElement.addEventListener('ended', () => {
121
- button.textContent = 'Play';
 
 
122
  currentAudio = null;
123
  });
124
  }
 
49
  border-radius: 5px;
50
  cursor: pointer;
51
  transition: background-color 0.3s;
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ }
56
+
57
+ .status-indicator {
58
+ width: 12px;
59
+ height: 12px;
60
+ border-radius: 50%;
61
+ background-color: #fff;
62
+ transition: background-color 0.3s;
63
+ }
64
+
65
+ .playing .status-indicator {
66
+ background-color: #2ecc71;
67
+ animation: pulse 1s infinite;
68
  }
69
 
70
+ .waveform-container {
71
+ width: 100px;
72
+ height: 40px;
73
+ margin-left: 15px;
74
  }
75
 
76
  audio {
77
  display: none;
78
  }
79
+
80
+ @keyframes pulse {
81
+ 0% { transform: scale(0.95); }
82
+ 50% { transform: scale(1.1); }
83
+ 100% { transform: scale(0.95); }
84
+ }
85
  </style>
86
  </head>
87
  <body>
 
102
 
103
  const container = document.getElementById('audioContainer');
104
  let currentAudio = null;
105
+ let audioContext = null;
106
+ let analyser = null;
107
+ let dataArray = null;
108
+ let animationFrameId = null;
109
 
110
  voices.forEach(voice => {
111
  const audioElement = document.createElement('audio');
 
118
  const nameSpan = document.createElement('span');
119
  nameSpan.textContent = voice.name;
120
 
121
+ const waveformCanvas = document.createElement('canvas');
122
+ waveformCanvas.className = 'waveform-container';
123
+
124
  const playButton = document.createElement('button');
125
  playButton.className = 'play-button';
126
+ playButton.innerHTML = `
127
+ <div class="status-indicator"></div>
128
+ <span>Play</span>
129
+ `;
130
+
131
+ playButton.onclick = () => toggleAudio(audioElement, playButton, waveformCanvas);
132
 
133
  itemDiv.appendChild(nameSpan);
134
+ itemDiv.appendChild(waveformCanvas);
135
  itemDiv.appendChild(playButton);
136
  container.appendChild(itemDiv);
137
  container.appendChild(audioElement);
138
  });
139
 
140
+ function setupAudioContext(audioElement) {
141
+ if (!audioContext) {
142
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
143
+ analyser = audioContext.createAnalyser();
144
+ analyser.fftSize = 256;
145
+ dataArray = new Uint8Array(analyser.frequencyBinCount);
146
+ }
147
+
148
+ const source = audioContext.createMediaElementSource(audioElement);
149
+ source.connect(analyser);
150
+ analyser.connect(audioContext.destination);
151
+ }
152
+
153
+ function drawWaveform(canvas) {
154
+ if (!analyser) return;
155
+
156
+ const ctx = canvas.getContext('2d');
157
+ const width = canvas.width;
158
+ const height = canvas.height;
159
+
160
+ function draw() {
161
+ animationFrameId = requestAnimationFrame(draw);
162
+ analyser.getByteTimeDomainData(dataArray);
163
+
164
+ ctx.fillStyle = '#f8f9fa';
165
+ ctx.fillRect(0, 0, width, height);
166
+ ctx.lineWidth = 2;
167
+ ctx.strokeStyle = '#3498db';
168
+ ctx.beginPath();
169
+
170
+ const sliceWidth = width / dataArray.length;
171
+ let x = 0;
172
+
173
+ for (let i = 0; i < dataArray.length; i++) {
174
+ const v = dataArray[i] / 128.0;
175
+ const y = v * height / 2;
176
+
177
+ if (i === 0) {
178
+ ctx.moveTo(x, y);
179
+ } else {
180
+ ctx.lineTo(x, y);
181
+ }
182
+
183
+ x += sliceWidth;
184
+ }
185
+
186
+ ctx.lineTo(width, height/2);
187
+ ctx.stroke();
188
+ }
189
+
190
+ draw();
191
+ }
192
+
193
+ function toggleAudio(audioElement, button, canvas) {
194
  if (currentAudio && currentAudio !== audioElement) {
195
  currentAudio.pause();
196
+ currentAudio.previousElementSibling.querySelector('.play-button').classList.remove('playing');
197
+ cancelAnimationFrame(animationFrameId);
198
  }
199
 
200
  if (audioElement.paused) {
201
+ if (!audioContext) {
202
+ setupAudioContext(audioElement);
203
+ }
204
  audioElement.play();
205
+ button.classList.add('playing');
206
+ button.querySelector('span').textContent = 'Pause';
207
+ drawWaveform(canvas);
208
  currentAudio = audioElement;
209
  } else {
210
  audioElement.pause();
211
+ button.classList.remove('playing');
212
+ button.querySelector('span').textContent = 'Play';
213
+ cancelAnimationFrame(animationFrameId);
214
  currentAudio = null;
215
  }
216
 
217
  audioElement.addEventListener('ended', () => {
218
+ button.classList.remove('playing');
219
+ button.querySelector('span').textContent = 'Play';
220
+ cancelAnimationFrame(animationFrameId);
221
  currentAudio = null;
222
  });
223
  }