mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-02 14:49:16 +02:00
186 lines
No EOL
6.1 KiB
JavaScript
186 lines
No EOL
6.1 KiB
JavaScript
var book = ePub();
|
|
var rendition;
|
|
|
|
var inputElement;
|
|
var audioClips = [];
|
|
var currentWord = 0;
|
|
var isPlaying = false;
|
|
function init() {
|
|
inputElement = document.getElementById("input");
|
|
|
|
inputElement.addEventListener('change', function (e) {
|
|
var file = e.target.files[0];
|
|
if (window.FileReader) {
|
|
var reader = new FileReader();
|
|
reader.onload = openBook;
|
|
reader.readAsArrayBuffer(file);
|
|
}
|
|
});
|
|
}
|
|
|
|
function openBook(e) {
|
|
var bookData = e.target.result;
|
|
var title = document.getElementById("title");
|
|
var next = document.getElementById("next");
|
|
var prev = document.getElementById("prev");
|
|
|
|
book.open(bookData, "binary");
|
|
/* console.log("opened book")
|
|
console.log(book) */
|
|
|
|
var rendition = book.renderTo("viewer", {
|
|
//manager: "continuous",
|
|
flow: "paginated",
|
|
width: "100%",
|
|
height: "100%",
|
|
snap: true
|
|
});
|
|
|
|
rendition.display();
|
|
var keyListener = function (e) {
|
|
|
|
// Left Key
|
|
if ((e.keyCode || e.which) == 37) {
|
|
rendition.prev();
|
|
}
|
|
|
|
// Right Key
|
|
if ((e.keyCode || e.which) == 39) {
|
|
rendition.next();
|
|
}
|
|
|
|
};
|
|
|
|
rendition.on("keyup", keyListener);
|
|
rendition.on("relocated", function (location) {
|
|
console.log(location);
|
|
initAudio();
|
|
});
|
|
|
|
next.addEventListener("click", function (e) {
|
|
rendition.next();
|
|
e.preventDefault();
|
|
}, false);
|
|
|
|
prev.addEventListener("click", function (e) {
|
|
rendition.prev();
|
|
e.preventDefault();
|
|
}, false);
|
|
|
|
document.addEventListener("keyup", keyListener, false);
|
|
|
|
|
|
}
|
|
function initAudio() {
|
|
var iframeList = document.getElementsByTagName("iframe");
|
|
audioClips = [];
|
|
for (let iframe of iframeList) {
|
|
var iframeDoc = iframe.contentDocument;
|
|
|
|
//get audio information
|
|
iframeDoc.querySelectorAll('par').forEach(par => {
|
|
var text = par.getElementsByTagName("text")[0]; //should only be one
|
|
var audio = par.getElementsByTagName("audio")[0]; //should only be one
|
|
var textId = text.getAttribute("src").split("#")[1];//text source format is page.xhtml#word
|
|
var textRef = iframeDoc.getElementById(textId);
|
|
var audioSrc = audio.getAttribute("src");
|
|
const contentType = "audio/mp3";
|
|
/*var sound = new Howl({
|
|
src: [`data:${contentType};base64,${audioSrc}`]
|
|
});*/
|
|
audioClips.push({
|
|
textId: textId,
|
|
text: textRef,
|
|
audio: audio,
|
|
clipBegin: parseFloat(audio.getAttribute("clipbegin")),
|
|
clipEnd: parseFloat(audio.getAttribute("clipend"))
|
|
//duration: 1000 * (parseFloat(audio.getAttribute("clipend")) - parseFloat(audio.getAttribute("clipbegin")))
|
|
})
|
|
});
|
|
//add next clip's start to the duration to account for pauses
|
|
for (let i = 0; i < audioClips.length - 1; i++) {
|
|
audioClips[i].duration = 1000 * (audioClips[i + 1].clipBegin - audioClips[i].clipBegin);
|
|
}
|
|
if (audioClips.length > 0) {
|
|
document.getElementById("audioplayer").style.visibility = "visible";
|
|
resetAudioToStart();
|
|
}
|
|
else {
|
|
document.getElementById("audioplayer").style.visibility = "hidden";
|
|
}
|
|
}
|
|
|
|
}
|
|
/**
|
|
* This is where the audio play/pause function should load and play everything on the page.
|
|
* Needs to loop through all available iframes because there may be 1-2 pages loaded separately on the page.
|
|
* I believe the audio tags will be in order per epub spec. Could look at play start and check if that's not the case.
|
|
* To play audio and go through highlighting the text and stopping at the right point, need to look at the clipBegin/clipEnd properties
|
|
* You could go through each audio tag and play/stop for each one but I think that'd cause some choppy behavior. Probably would be smoother to get the start/end for the page,
|
|
* and then track the time so that you can track the word for highlighting and pausing.
|
|
*
|
|
*
|
|
* Something to consider: will tracking the pages like this get messed up if the device rotates and only shows one page?
|
|
*/
|
|
function playPause() {
|
|
if (audioClips.length > 0) {
|
|
if (isPlaying) {
|
|
pauseAudio();
|
|
}
|
|
else {
|
|
playAudio();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* The audio is the same for the whole book, need to play/pause the same audio tag
|
|
*/
|
|
function playAudio() {
|
|
isPlaying = true;
|
|
highlightWord();
|
|
audioClips[0].audio.play();
|
|
document.getElementById("playButton").textContent = "Pause";
|
|
}
|
|
function pauseAudio() {
|
|
isPlaying = false;
|
|
audioClips[0].audio.pause();
|
|
document.getElementById("playButton").textContent = "Play";
|
|
}
|
|
function resetAudioToStart() {
|
|
if (currentWord > 0)
|
|
audioClips[currentWord - 1].text.setAttribute("style", "");
|
|
currentWord = 0;
|
|
pauseAudio();
|
|
audioClips[0].audio.currentTime = audioClips[currentWord].clipBegin;
|
|
}
|
|
function resetAudioToWord() {
|
|
audioClips[0].audio.currentTime = audioClips[currentWord].clipBegin;
|
|
}
|
|
/**
|
|
* To highlight text with audio, search for the span with the id that matches the #id in the text src wrapping the audio. Each par tag has a text with source and the audio.
|
|
* Add a css highlight class to the span, then remove when moving to the next word.
|
|
*/
|
|
function highlightWord() {
|
|
//don't increment words if the audio is ended
|
|
if (currentWord >= audioClips.length) {
|
|
resetAudioToStart();
|
|
return;
|
|
}
|
|
if (!isPlaying) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* note: using class add/remove doesn't work with iframes because the css is separate
|
|
*/
|
|
|
|
//highlight current word
|
|
if (currentWord > 0)
|
|
audioClips[currentWord - 1].text.setAttribute("style", "");
|
|
|
|
audioClips[currentWord].text.setAttribute("style", "background-color:yellow;");
|
|
//setup timer for when word is done being read
|
|
const myTimeout = setTimeout(highlightWord, audioClips[currentWord].duration);
|
|
//increment word index
|
|
currentWord++;
|
|
} |