Sound auf :hover abspielen

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Wenn Sie im Internet nach Möglichkeiten suchen, wie man mit CSS einen Sound abspielt, werden Sie

  1. Einiges über Counter Strike: Source finden
  2. Einiges über play-during und cue-before und Dinge, die vielversprechend aussehen, aber eigentlich für akustische Stylesheets (Barrierefreiheit / Screenreader-Zeug) gedacht sind, und nicht nur dafür, wie man Eselschreie erzeugt, wenn man in irgendeinem beliebigen Browser über einen Menüpunkt fährt.

Ich würde behaupten, dass Töne Teil des Designs sind und daher die Möglichkeit, sie abzuspielen/auszulösen, in CSS gehört, aber leider sind wir noch nicht so weit. Um Töne abzuspielen, wenn die Maus über einen bestimmten Bereich fährt, müssen wir auf HTML5 oder Flash zurückgreifen. Aber niemand hier möchte sich mit Flash beschäftigen, oder? Also machen wir es mit HTML5, das Töne über sein <audio>-Element abspielen kann (Firefox 3.5+, Chrome 3+, Opera 10.5+, Safari 4+, IE 9+). Um eine möglichst breite Browserunterstützung zu erhalten, machen wir es wie folgt mit einer MP3-Quelle (WebKit und IE) und einer OGG-Quelle (Firefox und Opera).

<audio>
	<source src="audio/beep.mp3"></source>
	<source src="audio/beep.ogg"></source>
	Your browser isn't invited for super fun audio time.
</audio>

Wenn Sie den obigen Code exakt in eine Seite einfügen, werden Sie nichts sehen oder hören. Wenn Sie ein kleines Player-Element wünschen, verwenden Sie unbedingt das Attribut `controls` (<audio controls>). Wenn es abgespielt werden soll, aber nicht sichtbar sein soll, verwenden Sie unbedingt das Element `autoplay` (<audio autoplay>). Oder beides...

Unser Ziel ist es, dass der Ton abgespielt wird, wenn die Maus über ein bestimmtes Element fährt, z. B. einen Menüpunkt. Leider können wir einem <audio>-Element über CSS keine Anweisungen geben, so dass wir JavaScript benötigen werden. Um den Ton mit JavaScript abzuspielen

var audio = document.getElementsByTagName("audio")[0];
audio.play();

// or with an ID

var audio = document.getElementById("mySoundClip");
audio.play();

Nehmen wir jQuery, einfach weil die Auswahl und der Umgang mit Ereignissen damit einfacher werden.

var audio = $("#mySoundClip")[0];
audio.play();

Um diesen Ton abzuspielen, wenn die Maus über ein bestimmtes Element fährt

var audio = $("#mySoundClip")[0];
$("nav a").mouseenter(function() {
  audio.play();
});

Ein anderer Weg...

Die Teaser-Seite für die Goodfoot Mobile App verwendet eine ähnliche Technik, um seltsame Grunzer (von Dave Rupert) abzuspielen, wenn man über den Yeti-Kerl fährt. Sie machen das, indem sie jedes Mal, wenn dieser Yeti-Kerl angefahren wird, ein neues Audio-Element in den DOM einfügen.

$("#speak").mouseenter(function(){
	$("<audio></audio>").attr({ 
		'src':'audio/'+Math.ceil(Math.random() * 5)+'.mp3', 
		'volume':0.4,
		'autoplay':'autoplay'
	}).appendTo("body");
});

Das könnte man wahrscheinlich noch etwas verbessern, um auch OGG zu unterstützen. Ich bin mir nicht sicher, was es mit dem `volume`-Attribut auf sich hat, das ist weder Standard noch wird es irgendwo unterstützt, wo ich es gesehen habe. Dies ist eine Modifikation von 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');     
});

Ich bin mit diesem Ansatz vollkommen einverstanden, da er gut zu funktionieren scheint und das ist letztendlich das Wichtigste. Nachdem der Ton einmal abgespielt wurde, scheint er gecached zu werden und spielt schnell ab, was gut ist.

Eine andere Möglichkeit wäre, alle drei Audio-Elemente sofort auf die Seite zu legen.

<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>

Dann zufällig eines auswählen und abspielen

$("#speak").mouseenter(function() {
    $("#sound-" + Math.ceil(Math.random() * 3))[0].play();
});

Versuche und Probleme: Überlappende Töne

Meine ursprüngliche Idee, damit herumzuspielen, war ein Navigationsmenü, das beim Überfahren mit der Maus einen kleinen Klickton abspielte. Sofort trat ein Problem auf: Man kann mit der Maus über Menüpunkte fahren und einen .play()-Befehl viel schneller auslösen, als der Ton abgespielt werden kann. Ein einzelnes Audio-Element kann nicht überlappend abspielen. Es ignoriert weitere Aufforderungen zu .play(), bis es abgeschlossen ist.

Mein erster Versuch war, .pause() zu verwenden, um den Ton zu stoppen, und dann wieder .play() aufzurufen, aber bei meinen Tests hilft das nicht viel. Es scheint die Pause zu respektieren, aber dann in vielen Fällen das Play nicht.

Der geschmeidigste Weg, den ich gefunden habe, war, das Audio-Element für jeden Menüpunkt zu duplizieren. Auf diese Weise hat jeder Menüpunkt seinen eigenen Audioclip zum Abspielen, und die Töne können sich überlappen.

$("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

Demo ansehen   Dateien herunterladen

Verwandt