Cuando busques en Google cómo reproducir un sonido con CSS, encontrarás:
- Algunas cosas sobre Counter Strike: Fuente
- algunas cosas sobre
play-during
ycue-before
y cosas que parecen prometedoras pero que en realidad son para hojas de estilo auditivas (cosas de accesibilidad / lector de pantalla) no solo para hacer gruñidos de burro cuando pasas el cursor sobre un elemento de menú en cualquier navegador antiguo
Yo diría que los sonidos son parte del diseño y, por lo tanto, la capacidad de reproducirlos/activarlos pertenece a CSS, pero lamentablemente, todavía no hemos llegado allí. Para reproducir sonidos cuando el mouse pasa sobre un área determinada, necesitaremos confiar en HTML5 o Flash. Pero nadie por aquí quiere tratar con Flash, ¿verdad? Así que hagámoslo con HTML5, que puede reproducir sonido a través de su <audio>
(Firefox 3.5+, Chrome 3+, Opera 10.5+, Safari 4+, IE 9+). Para obtener la mayor compatibilidad posible con el navegador, lo haremos así con una fuente MP3 (WebKit e IE) y una fuente OGG (Firefox y Opera).
<audio>
<source src="https://css-tricks.com/play-sound-on-hover/audio/beep.mp3"></source>
<source src="https://css-tricks.com/play-sound-on-hover/audio/beep.ogg"></source>
Your browser isn't invited for super fun audio time.
</audio>
Si inserta el código exactamente como se indica arriba en una página, no verá ni escuchará nada. Si desea un pequeño elemento de jugador, asegúrese de usar el atributo de controles (<audio controls>
). Si desea que se reproduzca pero no se vea, asegúrese de utilizar el elemento de reproducción automática (<audio autoplay>
). O ambos…
Nuestro objetivo es hacer que el sonido se reproduzca cuando el mouse se desplaza sobre un elemento determinado, como un elemento de menú. Una vez más, lamentablemente, no podemos decirle a un <audio>
elemento qué hacer a través de CSS, por lo que necesitaremos JavaScript. Para reproducir el sonido con JavaScript:
var audio = document.getElementsByTagName("audio")[0];
audio.play();
// or with an ID
var audio = document.getElementById("mySoundClip");
audio.play();
Usemos jQuery, solo porque facilitará la selección y el manejo de eventos.
var audio = $("#mySoundClip")[0];
audio.play();
Entonces, para hacer que este sonido comience a reproducirse cuando el mouse pasa sobre un elemento determinado:
var audio = $("#mySoundClip")[0];
$("nav a").mouseenter(function() {
audio.play();
});
De otra manera…
La página teaser de la aplicación móvil Goodfoot utiliza una técnica similar para reproducir ruidos de gemidos extraños (a través de Dave Rupert) cuando pasas el cursor sobre el tipo yeti. Lo hacen inyectando un nuevo elemento de audio en el DOM cada vez que se desplaza el tipo yeti:
$("#speak").mouseenter(function(){
$("<audio></audio>").attr({
'src':'audio/'+Math.ceil(Math.random() * 5)+'.mp3',
'volume':0.4,
'autoplay':'autoplay'
}).appendTo("body");
});
Eso probablemente podría mejorarse un poco, para admitir OGG también. No estoy seguro de qué se trata el atributo de volumen, eso no es una especificación ni es compatible en ningún lugar que haya visto. Esta es una modificación de Jeffrey Way:
function addSource(elem, path) {
$('<source>').attr('src', path).appendTo(elem);
}
$("#speak").mouseenter(function(){
var audio = $('<audio />', {
autoPlay : 'autoplay'
});
addSource(audio, 'audio/'+Math.ceil(Math.random() * 5)+'.mp3');
addSource(audio, 'audio/'+Math.ceil(Math.random() * 5)+'.ogg');
audio.appendTo('body');
});
Estoy totalmente de acuerdo con este enfoque, ya que parece funcionar bien y ese es el resultado final. Después de que el sonido se ha reproducido una vez, parece almacenarse en caché y reproducirse rápidamente, lo cual es bueno.
Otra forma de manejarlo sería colocar los tres elementos de audio en la página de inmediato.
<audio preload="auto" id="sound-1" > ... src & fallback ... </audio>
<audio preload="auto" id="sound-2" > ... src & fallback ... </audio>
<audio preload="auto" id="sound-3" > ... src & fallback ... </audio>
Luego elige al azar uno para jugar:
$("#speak").mouseenter(function() {
$("#sound-" + Math.ceil(Math.random() * 3))[0].play();
});
Pruebas y problemas: sonidos superpuestos
Mi idea original para jugar con esto era un menú de navegación que emitía un pequeño sonido de clic al pasar el cursor sobre ellos. Inmediatamente esto descubrió un problema: puede pasar el cursor sobre los elementos del menú que activan un .play()
mucho más rápido de lo que ese sonido puede terminar de reproducirse. Un solo elemento de audio no puede reproducir su propio sonido de forma superpuesta. Simplemente ignora otras solicitudes de .play()
hasta que se complete.
Mi primer intento fue usar .pause()
para detener la reproducción y luego .play()
de nuevo, pero en mis pruebas eso no ayuda mucho. Parece honrar la pausa pero luego no el juego en muchos casos.
La forma más sencilla que pude encontrar para hacerlo fue duplicar el elemento de audio para cada elemento del menú. De esa manera, cada elemento del menú tiene su propio clip de audio para reproducir y los sonidos pueden superponerse
$("nav a") // loop each menu item
.each(function(i) {
if (i != 0) { // only clone if more than one needed
$("#beep")
.clone()
.attr("id", "beep-" + i)
.appendTo($(this).parent());
}
$(this).data("beeper", i); // save reference
})
.mouseenter(function() {
$("#beep-" + $(this).data("beeper"))[0].play();
});
$("#beep").attr("id", "beep-0"); // get first one into naming convention
Ver demostración Descargar archivos
Relacionado
- Screencast #59: Incrustación de audio