melpomene/comic_reader.js

268 lines
6.8 KiB
JavaScript

PAGE_TRANSITION_SPEED = "1.5s"
READER_FRAME = document.getElementById("reader-frame")
READER_PAGES = document.getElementById("reader-pages")
FOCUS_OVERLAY = document.getElementById("focus-overlay")
CURRENT_ZOOM = 0
CURRENT_PAGE = 1
CURRENT_WIDTH = 0
CURRENT_HEIGHT = 0
CURRENT_X = 0
CURRENT_Y = 0
IS_PAGE_MODE = false
// ===========
// UTILITIES
// ===========
// Zooms utilites
// --------------
function getFirstZoomOfPage(pageNumber){
for (var zoom_idx = 0; zoom_idx < zooms.length; zoom_idx++){
if (zooms[zoom_idx][0] == pageNumber) {
return zoom_idx
}
}
}
function getLastZoomOfPage(pageNumber){
let res = null
for (var zoom_idx = 0; zoom_idx < zooms.length; zoom_idx++){
if (zooms[zoom_idx][0] == pageNumber) {
res = zoom_idx
}
if (res != null && zooms[zoom_idx][0] != pageNumber) {
break
}
}
return res
}
// Dimensions utilites
// -------------------
function getPagesCount() {
return READER_PAGES.childElementCount
}
function pageOriginalHeight() {
return parseInt(READER_PAGES.dataset.pagesHeight)
}
function pageOriginalWidth() {
return parseInt(READER_PAGES.dataset.pagesWidth)
}
function readerFrameRatio() {
return READER_FRAME.clientWidth / READER_FRAME.clientHeight
}
function pageRatio() {
return READER_PAGES.dataset.pagesWidth / READER_PAGES.dataset.pagesHeight
}
function isFrameRatioWiderThanPage(){
return readerFrameRatio() > pageRatio()
}
function pageToFrameScaleFactor(useHeight){
// The scale factor to apply to a page so it exactly fit in the reader frame
if (useHeight) {
return READER_FRAME.clientHeight / pageOriginalHeight()
}
return READER_FRAME.clientWidth / pageOriginalWidth()
}
function totalPagesWidth() {
// The width of all cumuled pages with scale factor applied
return pageOriginalWidth() * getPagesCount()
}
// =========
// ACTIONS
// =========
function initReader(){
moveReaderDisplayToZoom(0)
for (var i = 0; i < READER_PAGES.children.length; i++) {
let img = READER_PAGES.children[i];
img.style.width = 100 / getPagesCount() + "%"
}
READER_PAGES.style.display = "flex"
READER_PAGES.hidden = false
}
function moveReaderDisplayToArea(pageNumber, width, height, posx, posy){
if (width == 0){
width = pageOriginalWidth()
}
if (height == 0){
height = pageOriginalHeight()
}
zoomRatio = width / height
if (readerFrameRatio() > zoomRatio) {
// Frame wider than zoom
var zoomToFrameScaleFactor = pageToFrameScaleFactor(true) * pageOriginalHeight() / height
var zoomToFrameCenteringOffset = [(READER_FRAME.clientWidth - width * zoomToFrameScaleFactor) / 2, 0]
updateFocusByWidth(width * zoomToFrameScaleFactor)
} else {
var zoomToFrameScaleFactor = pageToFrameScaleFactor(false) * pageOriginalWidth() / width
var zoomToFrameCenteringOffset = [0, (READER_FRAME.clientHeight - height * zoomToFrameScaleFactor) / 2]
updateFocusByHeight(height * zoomToFrameScaleFactor)
}
previousPagesOffset = pageOriginalWidth() * (pageNumber - 1) * zoomToFrameScaleFactor
READER_PAGES.style.width = totalPagesWidth() * zoomToFrameScaleFactor + "px"
READER_PAGES.style.height = pageOriginalHeight() * zoomToFrameScaleFactor + "px"
READER_PAGES.style.left = (- posx * zoomToFrameScaleFactor + zoomToFrameCenteringOffset[0] - previousPagesOffset) + "px"
READER_PAGES.style.top = (- posy * zoomToFrameScaleFactor + zoomToFrameCenteringOffset[1]) + "px"
CURRENT_PAGE = pageNumber
CURRENT_WIDTH = width
CURRENT_HEIGHT = height
CURRENT_X = posx
CURRENT_Y = posy
}
function moveReaderDisplayToPage(pageNumber) {
moveReaderDisplayToArea(pageNumber, 0, 0, 0, 0)
}
function moveReaderDisplayToZoom(index) {
moveReaderDisplayToArea(zooms[index][0], zooms[index][1], zooms[index][2], zooms[index][3], zooms[index][4])
CURRENT_ZOOM = index
}
function updateFocusByWidth(width){
side_width = (READER_FRAME.clientWidth - width) / 2
FOCUS_OVERLAY.style.gridTemplateColumns = side_width +"px auto " + side_width + "px"
FOCUS_OVERLAY.style.gridTemplateRows = "0px auto 0px";
}
function updateFocusByHeight(height){
side_width = (READER_FRAME.clientHeight - height) / 2
FOCUS_OVERLAY.style.gridTemplateRows = side_width +"px auto " + side_width + "px"
FOCUS_OVERLAY.style.gridTemplateColumns = "0px auto 0px";
}
function moveReader(to_next, move_page) {
if (move_page){
if (IS_PAGE_MODE){
if (to_next && CURRENT_PAGE < getPagesCount()) {
moveReaderDisplayToPage(CURRENT_PAGE + 1)
IS_PAGE_MODE = true
}
else if (CURRENT_PAGE > 1) {
moveReaderDisplayToPage(CURRENT_PAGE - 1)
IS_PAGE_MODE = true
}
}
else {
if (to_next && CURRENT_PAGE < getPagesCount()) {
moveReaderDisplayToPage(CURRENT_PAGE + 1)
IS_PAGE_MODE = true
}
else {
moveReaderDisplayToPage(CURRENT_PAGE)
IS_PAGE_MODE = true
}
}
} else {
if (IS_PAGE_MODE){
if (to_next) {
moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE))
IS_PAGE_MODE = false
}
else {
if (CURRENT_PAGE == 1) {
moveReaderDisplayToZoom(0)
IS_PAGE_MODE = false
} else {
moveReaderDisplayToZoom(getLastZoomOfPage(CURRENT_PAGE - 1))
IS_PAGE_MODE = false
}
}
} else {
if (to_next && CURRENT_ZOOM < zooms.length - 1) {
moveReaderDisplayToZoom(CURRENT_ZOOM + 1)
IS_PAGE_MODE = false
}
else if (CURRENT_ZOOM > 0) {
moveReaderDisplayToZoom(CURRENT_ZOOM - 1)
IS_PAGE_MODE = false
}
}
}
}
function handleKeyPress(key, has_ctrl){
if (key == "ArrowRight") {
moveReader(true, has_ctrl)
}
else if (key == "ArrowLeft") {
moveReader(false, has_ctrl)
}
}
// ======
// INIT
// ======
window.addEventListener("load", (event) => {
initReader()
});
addEventListener("resize", (event) => {
moveReaderDisplayToArea(CURRENT_PAGE, CURRENT_WIDTH, CURRENT_HEIGHT, CURRENT_X, CURRENT_Y)
});
addEventListener("keydown", (event) => {
handleKeyPress(event.key, event.ctrlKey)
});