Signatur
Beschreibung
createPanner() ist eine Fabrikmethode von BaseAudioContext und damit sowohl auf AudioContext als auch auf OfflineAudioContext verfügbar. Sie liefert einen PannerNode, der ein Audiosignal räumlich einordnet: Position, Ausrichtung, Entfernungsdämpfung und Richtcharakteristik (Schallkegel) der Quelle lassen sich einstellen, jeweils relativ zum AudioListener des Kontexts (context.listener).
Du brauchst den Knoten für Spiele, VR-/WebXR-Anwendungen, interaktive Klanginstallationen oder überall dort, wo Klänge von einem bestimmten Ort im Raum kommen sollen. Für einfaches Links-Rechts-Panning in Stereo ist der deutlich leichtere StereoPannerNode (createStereoPanner()) die bessere Wahl.
Die Methode ist gleichwertig zum Konstruktor new PannerNode(context, options). Mit dem Konstruktor kannst du alle Eigenschaften gleich beim Erzeugen setzen, zum Beispiel panningModel, distanceModel, positionX oder coneInnerAngle. Moderner Code bevorzugt deshalb meist den Konstruktor. Position und Ausrichtung sind AudioParams (positionX/Y/Z, orientationX/Y/Z) und lassen sich somit auch zeitgenau automatisieren.
Rückgabewert
PannerNode mit Standardwerten: panningModel = "equalpower", distanceModel = "inverse", Position (0, 0, 0), Ausrichtung (1, 0, 0), refDistance = 1, maxDistance = 10000, rolloffFactor = 1, coneInnerAngle = coneOuterAngle = 360.Beispiele
Oszillator im 3D-Raum rechts vom Hörer platzieren
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const panner = ctx.createPanner();
panner.panningModel = 'HRTF'; // realistischer Klang über Kopfhörer
panner.distanceModel = 'inverse';
panner.positionX.value = 3; // 3 Einheiten rechts
panner.positionY.value = 0;
panner.positionZ.value = -1; // leicht vor dem Hörer
osc.connect(panner).connect(ctx.destination);
document.querySelector('#play').addEventListener('click', async () => {
await ctx.resume(); // Autoplay-Sperre aufheben
osc.start();
osc.stop(ctx.currentTime + 2);
});
Klangquelle kreisförmig um den Hörer bewegen (Automatisierung)
const ctx = new AudioContext();
const panner = ctx.createPanner();
panner.panningModel = 'HRTF';
const osc = new OscillatorNode(ctx, { frequency: 330 });
osc.connect(panner).connect(ctx.destination);
const radius = 4;
const start = ctx.currentTime;
for (let i = 0; i <= 80; i++) {
const t = start + i * 0.05; // 4 Sekunden gesamt
const angle = (i / 80) * 2 * Math.PI;
panner.positionX.linearRampToValueAtTime(Math.sin(angle) * radius, t);
panner.positionZ.linearRampToValueAtTime(-Math.cos(angle) * radius, t);
}
osc.start(start);
osc.stop(start + 4);
Lautsprecher mit Richtcharakteristik in einem Spiel
const ctx = new AudioContext();
const response = await fetch('/sounds/radio.mp3');
const buffer = await ctx.decodeAudioData(await response.arrayBuffer());
const source = new AudioBufferSourceNode(ctx, { buffer, loop: true });
const panner = ctx.createPanner();
// Schallkegel: nach vorne laut, hinten stark gedämpft
panner.coneInnerAngle = 60;
panner.coneOuterAngle = 180;
panner.coneOuterGain = 0.1;
panner.orientationX.value = 0;
panner.orientationZ.value = 1; // zeigt in Richtung +Z
panner.refDistance = 1;
panner.maxDistance = 50;
panner.rolloffFactor = 1.5;
panner.positionZ.value = -5;
source.connect(panner).connect(ctx.destination);
source.start();
// Hörer bewegt sich (z. B. aus der Spielschleife)
const movePlayer = (x, z) => {
ctx.listener.positionX.setValueAtTime(x, ctx.currentTime);
ctx.listener.positionZ.setValueAtTime(z, ctx.currentTime);
};
movePlayer(0, 2);
// Wichtig · Fallstricke
- Veraltete API:
panner.setPosition(),panner.setOrientation()sowielistener.setPosition()sind veraltet. Verwende stattdessen dieAudioParamspositionX/Y/ZundorientationX/Y/Z. Firefox unterstützt dieAudioParam-Eigenschaften amAudioListenerteilweise noch nicht, deshalb bei Bedarf per Feature-Erkennung aufsetPosition()zurückfallen. - Leistung:
"HRTF"klingt deutlich realistischer (vor allem über Kopfhörer), rechnet aber viel mehr als"equalpower". Bei vielen gleichzeitigen Quellen spürbar. - Der Knoten gibt immer ein Stereo-Signal aus. Die Eingabe ist auf maximal 2 Kanäle begrenzt (
channelCountMode = "clamped-max"). - Das Koordinatensystem ist rechtshändig: Der Hörer blickt standardmäßig in Richtung −Z. Positive Z-Werte liegen also hinter ihm.
maxDistancewirkt nur beidistanceModel = "linear"als harte Grenze. Bei"inverse"und"exponential"wird die Dämpfung ab dieser Entfernung nicht weiter verstärkt.- Wegen der Autoplay-Richtlinien startet ein
AudioContextoft im Zustand"suspended". Rufctx.resume()nach einer Nutzeraktion auf.