You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
9.6 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<title>EPUB</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jszip/3.1.5/jszip.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/epubjs@0.3.88/dist/epub.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const html = document.querySelector('html')
let fontSize = window.innerWidth / 10
fontSize = fontSize > 50 ? 50 : fontSize
html.style.fontSize = fontSize + 'px'
})
</script>
<style>
* {
padding: 0;
margin: 0;
}
.mask {
position: absolute;
display: flex;
left: 0;
width: 100%;
height: 100%;
flex-direction: column;
}
.meun {
display: flex;
height: 1rem;
align-items: center;
}
#toc {
flex: 1;
z-index: 100;
font-size: .3rem;
padding-left: .4rem;
color: #333;
}
#page {
z-index: 100;
font-size: .3rem;
color: #333;
padding-right: 0.4rem;
text-align: right;
flex: 0 0 .5rem;
}
#load {
z-index: 100;
font-size: .3rem;
color: #333;
padding-right: 0.4rem;
text-align: right;
flex: 0 0 .5rem;
}
#toc-content {
position: absolute;
display: flex;
top: 0;
right: 0;
z-index: 102;
min-width: auto;
max-width: 80%;
height: 100%;
background: white;
flex-direction: column
}
#toc-mask {
position: absolute;
top: 0;
left: 0;
z-index: 101;
width: 100%;
height: 100%;
background: rgba(51, 51, 51, .8);
}
.intro {
width: 100%;
height: 2.4rem;
padding: .2rem .4rem;
box-sizing: border-box;
height: 3rem;
display: flex;
border-bottom: .1rem solid #f4f4f4;
}
.txt {
display: flex;
flex: 1;
align-items: center;
padding: 0 .2rem;
font-size: .3rem;
}
#content {
overflow-y: auto;
}
.item {
padding: .2rem .4rem;
border-bottom: .07rem solid #f4f4f4;
font-size: .4rem;
color: #333;
}
#open {
display: flex;
flex: 1;
z-index: 100;
font-size: .4rem;
color: #333;
align-items: flex-end;
justify-content: center;
}
#open span {
padding: .3rem .3rem;
border: .05rem solid #333;
border-radius: .2rem;
}
.read {
display: flex;
flex: 1 1 auto;
}
#prev {
flex: 0 0 2rem;
z-index: 100;
}
#viewer {
flex: 1;
}
#next {
flex: 0 0 2rem;
z-index: 100;
}
.save {
display: flex;
}
.box {
padding: .2rem .2rem;
justify-content: center;
border-bottom: .1rem solid #f4f4f4;
}
.jump {
display: flex;
height: 1rem;
border-bottom: .1rem solid #f4f4f4;
}
.jump input {
flex: 1;
padding: .1rem .1rem;
margin: .2rem .2rem .2rem .4rem;
outline: none;
font-size: .3rem;
}
.jump span {
flex: 0 0 1rem;
}
</style>
</head>
<body>
<div id="ebook">
<div class="mask">
<div id="open">
<span
onclick="document.getElementById('input').click();document.getElementById('open').style.display = 'none'">选择本地书籍</span>
<input type="file" id="input" style="display: none;">
</div>
<div class="read">
<div id="prev" onclick="rendition.prev()"></div>
<div id="viewer"></div>
<div id="next" onclick="rendition.next()"></div>
</div>
<div class="meun">
<div id="toc" onclick="showhide()"></div>
<div id="page"></div>
<div id="load"></div>
</div>
<div id="toc-mask" style="display: none;" onclick="showhide()"></div>
<div id="toc-content" style="display: none;">
<div class="intro">
<img id="cover">
<div style="display: flex;flex: 1;flex-direction: column;overflow-y: auto;">
<div id="title" class="txt"></div>
<div id="author" class="txt"></div>
<div id="publisher" class="txt"></div>
<div id="pubdate" class="txt"></div>
</div>
</div>
<div class="save">
<div class="txt box" onclick="save()">存档</div>
<div class="txt box" onclick="get()">读档</div>
<div class="txt box" onclick="del()">删档</div>
</div>
<div class="jump">
<input id="jump" type="number" placeholder="0-1之间的数字如0.25"
oninput="if(value>1)value=1;if(value<0)value=0">
<span class="txt" onclick="jump()">跳转</span>
</div>
<div id="content"></div>
</div>
</div>
</div>
<script>
let url = location.search.substring(3);
if (url !== "") {
var book = ePub(url);
document.getElementById("open").style.display = "none"
} else {
var book = ePub();
var 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;
book.open(bookData, "binary");
}
}
//渲染
var rendition = book.renderTo("ebook", {
with: window.innerWidth,
height: window.innerHeight - 20
});
rendition.display();
book.ready
.then(() => {
var local = localStorage.getItem(book.key() + '-locations');
if (local) {
return book.locations.load(local);
} else {
return book.locations.generate();
}
})
.then(locations => {
localStorage.setItem(book.key() + '-locations', book.locations.save());
})
// 目录
book.loaded.navigation.then(toc => {
var read = localStorage.getItem(book.key() + '-read');
if (read) {
rendition.display(read);
}
var $content = document.getElementById("content");
toc.forEach(item => {
var div = document.createElement("div");
div.className = "item";
div.textContent = item.label;
div.addEventListener("click", () => {
rendition.display(item.href);
showhide()
});
$content.appendChild(div)
})
})
//简介
book.loaded.metadata.then(meta => {
var $title = document.getElementById("title");
var $author = document.getElementById("author");
var $cover = document.getElementById("cover");
var $publisher = document.getElementById("publisher");
var $pubdate = document.getElementById("pubdate");
$title.textContent = `书名:${meta.title}`;
$author.textContent = `作者:${meta.creator}`;
$publisher.textContent = `出版社:${meta.publisher}`;
$pubdate.textContent = `时间:${meta.pubdate}`;
if (book.archive) {
book.archive.createUrl(book.cover)
.then(url => {
$cover.src = url;
})
} else {
$cover.src = book.cover;
}
});
//进度显示
rendition.on('relocated', location => {
var percent = book.locations.percentageFromCfi(location.start.cfi);
var $page = document.getElementById("page");
var $load = document.getElementById("load");
$page.textContent = location.end.displayed.page + '/' + location.end.displayed.total;
$load.textContent = Math.fround(percent * 100).toFixed(1) + '%';
})
//章节名显示
rendition.on("rendered", section => {
var $toc = document.getElementById("toc");
$toc.textContent = "目录";
$toc.textContent = book.navigation.get(section.href).label;
})
function showhide() {
var $toc_content = document.getElementById("toc-content")
var $mask = document.getElementById("toc-mask")
if ($toc_content.style.display == "none") {
$toc_content.style.display = ""
$mask.style.display = ""
} else {
$toc_content.style.display = "none"
$mask.style.display = "none"
}
}
function jump() {
$jump = document.getElementById("jump").value;
rendition.display(book.locations.cfiFromPercentage($jump));
showhide();
document.getElementById("jump").value = "";
}
function save() {
localStorage.setItem(book.key() + '-read', rendition.currentLocation().start.cfi)
showhide()
}
function get() {
rendition.display(localStorage.getItem(book.key() + '-read'));
showhide()
}
function del() {
localStorage.removeItem(book.key() + '-read');
showhide()
}
</script>
</body>
</html>