alexanderkatz / html5-audio Goto Github PK
View Code? Open in Web Editor NEWCustom HTML5 audio interface. I am using javascript to interface with the HTML5 audio tag, so I can create a player that has a standard appearance across multiple browsers.
Custom HTML5 audio interface. I am using javascript to interface with the HTML5 audio tag, so I can create a player that has a standard appearance across multiple browsers.
My timeline just works after i played the audio once till the end.
After pressing play button again, the timeline works fine for me.
But initially it isnt working.
Any idea?
This code of yours prevented my additional hacks (such as volume control ) from working:
document.addEventListener("DOMContentLoaded", function(event) {
/* DOMContentLoaded*/
});
When I deleted it, my stuff worked. Then again, I'm not savvy at coding. Perhaps my hacks could have worked with your code had I known how to make it work.
You can see it working here with additional styling, looping, and volume control: https://aleks-volume.blogspot.com/
I've hidden the player until it gets appended. However, it can stay visible and un-appended and work just fine.
These are a few of the mechanics I changed:
(These are links to music set inside a list, but the code isn't showing it)
<li><a src='http://www.alexkatz.me/codepen/music/chooseyourweapon.mp3'> Choose</a></li>
<li><a src='http://www.alexkatz.me/codepen/music/interlude.mp3'>Interlude</a></li>
<li><a src='http://www.alexkatz.me/codepen/music/scriptures.mp3'>Scriptures</a></li>
<audio></audio>
var duration = audio.duration; // and all the rest of the "music"s have been changed to "audio"s as well.
var links = document.getElementsByTagName('a');
var link = links;
audioplayer.style.visibility = 'hidden';
// Actions that happen when a link is clicked:
var links = document.getElementsByTagName('a');
var link = links;
for (var m = 0; m < links.length; m++) {
link[m].addEventListener('click', function() {
// Add the classes 'current' and 'visited' to the selected link:
var selected = document.getElementsByClassName('current');
if (selected.length > 0) {
selected[0].className = selected[0].className.replace('current', '');
}
// To work, 'visited' must precede 'current':
this.className += "visited current";
// Attach the player to a 'li' tag. If attached to an 'a' tag,
// the player takes on the tag's styling.
var li = this.parentNode;
li.appendChild(audioplayer);
audioplayer.style.visibility = 'visible';
// Get audio source from an 'a' tag instead of an 'audio' tag:
var source = selected[0].getAttribute('src');
audio.src = source;
audio.play();
})
}; // Actions are finished for the selected link.
};
audio.onplaying = function(){
// remove play, add pause
pButton.className = "pause";
};
// At audio file's end, reset timeline to the beginning.
audio.onended = function(){
playhead.style.marginLeft = "0px";
pButton.className = "play";
};
The original example cannot be used when positioned absolute, relative or fixed in a standard Dom document instead of an iFrame (as is used in the demo). All the calculations used for positioning the elements are done relative to the parent element. Because of this the demo immediately breaks when absolute, relative or fixed positioning are used in the CSS.
I added a function to get the right position (cross browser) and to make all caculations work (even when users zoom in or out and the pixel size varies the real offset is calculated exactly right) . In this way it can also be used in scrollable and resizeable windows if some event listeners and an update routine are added for that purpose (see remarks in the adapted script below). I also added some conditions to avoid errors in case audio.src is empty when the script is initialized.
e.pageX is replaced by e.clientX for wider browser support!
I just hope it will save somebody a lot of time!!!
Maybe Alex can adapt the demo with the below code: ( the last function has been added and some variables in the script have been adapted to use the result values of that function)
HAVE FUN!!!!!
function showControls() {
/*---------------------------------------------------------------------------------------------------------------------------------------
Script source; http://alexkatz.me/posts/building-a-custom-html5-audio-player-with-javascript/
Icon source: Icon source: https://www.iconfinder.com/search/?q=play&maximum=16
REMARKS !! :
- By adding the function 'getPosition(el)' the script also works fine for absolute/relative and fixed positioning.
Also scrolling and window resize can be used by adding listeners for those events and updating the position for them.
- e.pageX is replaced by e.clientX, this works just as well, with e.clientX the script is also stable and this has the advantage of a
wider browser support. e.pageX is not supported by IE 8 (only from IE 9 and up). Although there is an issue with e.clientX in lower
IE versions from 7 and down described at http://help.dottoro.com/ljsqnefp.php in the following way:
In Internet Explorer earlier than version 8, the clientX property retrieves the position of the mouse in physical pixel size,
while from version 8, it returns the position in logical pixel size. What does it mean?
If the browser is not at the normal zoom level (the user has the ability to zoom in or out a web page: CTRL and +, CTRL and -),
the clientX property works differently from version 8 than in earlier versions. The position of the mouse pointer is calculated
in the default pixel size in Internet Explorer before version 8 even if the current pixel size in the document is different.
From Internet Explorer 8 and in Firefox, Opera, Google Chrome and Safari, the position is calculated in the current pixel size.
So then e.clientX is not influenced by user zooming.
----------------------------------------------------------------------------------------------------------------------------------------*/
// get references to variables
var audio = document.getElementById('audio'); // audio object
var pButton = document.getElementById('pButton'); // play button
var playhead = document.getElementById('playhead'); // moving playhead
var timeline = document.getElementById('timeline'); // timeline for playhead
var timelineWidth = timeline.offsetWidth - playhead.offsetWidth; // timeline width adjusted for playhead
if (audio.src) { // 'duration' is globally declared (see top of script) to keep track of
duration = audio.duration; // the duration of the audio clip ( 'zero' if audio.src = '' )
} // duration is constantly updated by EventListener "canplaythrough"
// !!!!!! in case of changing multiple media sources !!!!!!!; be sure to
// get the new value of 'audio.duration' every time 'audio.src' is changed
// timeupdate event listener
audio.addEventListener("timeupdate", timeUpdate, false);
// makes timeline clickable
timeline.addEventListener("click", function (event) {
moveplayhead(event);
if (!duration == 0 || !duration == NaN) { // this is to avoid errors if no audio is loaded; audio.src=''
audio.currentTime = duration * clickPercent(event);
}
}, false);
// returns click as decimal (.77) of the total timelineWidths
function clickPercent(e) {
return (e.clientX - getPosition(timeline).x) / timelineWidth;
}
// makes playhead draggable
playhead.addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
// boolean value so that mouse is moved on mouseUp only when the playhead is released
var onplayhead = false;
// mouseDown EventListener
function mouseDown() {
onplayhead = true;
window.addEventListener('mousemove', moveplayhead, true);
audio.removeEventListener('timeupdate', timeUpdate, false);
}
// mouseUp EventListener
// getting input from all mouse clicks
function mouseUp(e) {
if (onplayhead == true) {
moveplayhead(e);
window.removeEventListener('mousemove', moveplayhead, true);
if (!duration == 0 || !duration == NaN) { // this is to avoid errors if no audio is loaded; audio.src=''
audio.currentTime = duration * clickPercent(e);
}
audio.addEventListener('timeupdate', timeUpdate, false);
}
onplayhead = false;
}
// mousemove EventListener
// Moves playhead as user drags
function moveplayhead(e) {
var newMargLeft = e.clientX - getPosition(timeline).x;
if (newMargLeft >= 0 && newMargLeft <= timelineWidth) {
playhead.style.marginLeft = newMargLeft + "px";
}
if (newMargLeft < 0) {
playhead.style.marginLeft = "0px";
}
if (newMargLeft > timelineWidth) {
playhead.style.marginLeft = timelineWidth + "px";
}
}
// timeUpdate synchronizes playhead position with current point in audio
function timeUpdate() {
var playPercent = timelineWidth * (audio.currentTime / duration);
playhead.style.marginLeft = playPercent + "px";
if (audio.currentTime == duration) {
pButton.className = "";
pButton.className = "play";
}
}
// gets audio file duration
audio.addEventListener("canplaythrough", function () {
duration = audio.duration;
}, false);
// getPosition(el) ; cross browser function to get an element's exact (absolute) position from the entry
// point(=html tag) of the DOM document. This is used to make the controls available in any positon.
// see document "Javascript; Get an Element's Position Using JavaScript.docx"
// N.B. ===>Deal with the page getting resized or scrolled: add the 2 below event listeners
// window.addEventListener("scroll", updatePosition, false);
// window.addEventListener("resize", updatePosition, false);
// and a function like this:
// function updatePosition() {
// add your code to update the position when your browser
// is resized or scrolled
// }
function getPosition(el) {
var xPos = 0;
var yPos = 0;
while (el) {
if (el.tagName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft);
yPos += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: xPos,
y: yPos
};
}
}
Hey ๐,
I wanted to have multiple audio players like this
but the second doesn't seem to work. I changed the ID of the second audio player and added it to a querySelector in the JS file, like this: var music = document.querySelector('#music', '#music1'); // id for audio element var duration; // Duration of audio clip var pButton = document.getElementById('pButton'); // play button var playhead = document.getElementById('playhead'); // playhead var timeline = document.getElementById('timeline'); // timeline
and my second audio looks like this in the HTML: `
<div id="wrapper">
<!--Audio Player Interface-->
<div id="audioplayer">
<button id="pButton" class="play"></button>
<div id="timeline">
<div id="playhead"></div>
</div>
</div>
</div>`
If someone could shed some light, that would be great! :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.