Rebel Artimus
commited on
Commit
·
16781b9
1
Parent(s):
37ea4c6
Add 2 files
Browse files- index.html +9 -19
- main.js +252 -0
index.html
CHANGED
|
@@ -1,19 +1,9 @@
|
|
| 1 |
-
|
| 2 |
-
<
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
<div class="card">
|
| 11 |
-
<h1>Welcome to your static Space!</h1>
|
| 12 |
-
<p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
|
| 13 |
-
<p>
|
| 14 |
-
Also don't forget to check the
|
| 15 |
-
<a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
|
| 16 |
-
</p>
|
| 17 |
-
</div>
|
| 18 |
-
</body>
|
| 19 |
-
</html>
|
|
|
|
| 1 |
+
<html><head><link href="https://cdn.jsdelivr.net/npm/daisyui@3.1.6/dist/full.css" rel="stylesheet" type="text/css" /><script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script><script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script><script defer src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js"></script><script type="module" src="main.js"></script><title>PDF Viewer</title></head><body>
|
| 2 |
+
<div class="container">
|
| 3 |
+
<div class="prose">
|
| 4 |
+
<h1><button class="btn reset">Reset</button></h1>
|
| 5 |
+
<div class="pagewrapper pageskip">
|
| 6 |
+
</div>
|
| 7 |
+
</div>
|
| 8 |
+
</div>
|
| 9 |
+
<script type="module" src="app.js"></script></body></html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { html } from "https://cdn.skypack.dev/pin/htm@v3.2.2-nao32m88/mode=imports,min/optimized/htm.js";
|
| 2 |
+
import "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio";
|
| 3 |
+
import { AlpineSome } from "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js";
|
| 4 |
+
|
| 5 |
+
const PDF_FILE_URL1 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/material.pdf";
|
| 6 |
+
const PDF_FILE_URL2 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/newspaper.pdf";
|
| 7 |
+
const PDF_FILE_URL3 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/plane.pdf";
|
| 8 |
+
|
| 9 |
+
const pdfCatalog = {};
|
| 10 |
+
|
| 11 |
+
class PDFViewer {
|
| 12 |
+
constructor(file_url, pdfDocument) {
|
| 13 |
+
this.file_url = file_url;
|
| 14 |
+
this.pdfDocument = pdfDocument;
|
| 15 |
+
this.pages = pdfDocument.pages;
|
| 16 |
+
this.current_page = 0;
|
| 17 |
+
this.zoom = 1;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
updatePage(current_page = 1, zoom = 1) {
|
| 21 |
+
if (current_page < 0) {
|
| 22 |
+
current_page = 1;
|
| 23 |
+
} else if (current_page > this.pages.length) {
|
| 24 |
+
current_page = this.pages.length;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
this.current_page = current_page;
|
| 28 |
+
this.zoom = zoom;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
render() {
|
| 32 |
+
this.disablePreviewPage();
|
| 33 |
+
|
| 34 |
+
const width = this.pages[0].getWidth();
|
| 35 |
+
const height = this.pages[0].getHeight();
|
| 36 |
+
|
| 37 |
+
const viewport = new THREE.PDFViewerViewport(width, height, this.zoom);
|
| 38 |
+
|
| 39 |
+
const scene = new THREE.Scene();
|
| 40 |
+
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000);
|
| 41 |
+
|
| 42 |
+
const uniforms = new THREE.PDFUniforms(UNIFORMS.TIME, UNIFORMS.RESOLUTION);
|
| 43 |
+
const control = new THREE.OrbitalControl();
|
| 44 |
+
camera.userData.JZBody = new THREE.TVCameraJz Mangn(control, uniforms);
|
| 45 |
+
|
| 46 |
+
const timeline = document.getElementById(" timeline");
|
| 47 |
+
control.time.time.connect(timeline.timeRange);
|
| 48 |
+
|
| 49 |
+
const light = new THREE.JILLigSecurityLED();
|
| 50 |
+
light.position.set(0, 0, 0);
|
| 51 |
+
|
| 52 |
+
const mesh = new THREE.Mesh(THREE.PDFGeometry(this.pages[this.current_page]), new THREE.PDFMaterial(this.PDF_URL, light, new THREE.LinearFilter(THREE.WrapMode.REPEAT, THREE.WrapMode.REPEAT)));
|
| 53 |
+
|
| 54 |
+
let mesh;
|
| 55 |
+
for (let i = 1; i < this.pages.length; i++) {
|
| 56 |
+
mesh = new THREE.Mesh(THREE.PDFGeometry(this.pages[i]), new THREE.PDFMaterial(this.PDF_URL, light, new THREE.LinearFilter(THREE.WrapMode.REPEAT, THREE.WrapMode.REPEAT)));
|
| 57 |
+
mesh.position.set(width * i / 100, 0, 0);
|
| 58 |
+
scene.add(mesh);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
const context = {
|
| 62 |
+
width: width,
|
| 63 |
+
height: height,
|
| 64 |
+
pdf_url: this.PDF_URL,
|
| 65 |
+
page: this.current_page + 1,
|
| 66 |
+
zoom: this.zoom,
|
| 67 |
+
eventDispatcher: new THREE.EventDispatcher()
|
| 68 |
+
};
|
| 69 |
+
|
| 70 |
+
const loader = new THREE.PDFLoader();
|
| 71 |
+
loader.load();
|
| 72 |
+
|
| 73 |
+
const ref = AlpineSome.template("<div id='main' class='rama medfnd allegBundle' rotate='0' position ='0,0,0'><div id='page' class='page<Transform>'><div class='page-box'>{{{page}}}</div></div></div>");
|
| 74 |
+
document.body.appendChild(ref.content);
|
| 75 |
+
|
| 76 |
+
for (let i = 1; i < this.pages.length; i++) {
|
| 77 |
+
const page_data = this.pages[i];
|
| 78 |
+
const page_el = document.createElement("div");
|
| 79 |
+
page_el.id = "page" + (i + 1);
|
| 80 |
+
page_e.classList.add("page-box");
|
| 81 |
+
page_e.innerHTML = page_data;
|
| 82 |
+
ref.content.appendChild(page_el);
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
//disabling & speeding up page switching
|
| 86 |
+
//disabled by default
|
| 87 |
+
const a = Alpine.document.querySelectorAll("#main .page");
|
| 88 |
+
for (let i = 1; i < a.length; i++) {
|
| 89 |
+
a[i].setAttribute("style", "transition-duration: 0s");
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
const hoverOffset = 20;
|
| 93 |
+
const hoverRange = 3;
|
| 94 |
+
const hoverInTimeout = 200;
|
| 95 |
+
const hoverOutTimeout = 200;
|
| 96 |
+
let hoverNotFound = 0;
|
| 97 |
+
let hoverStart = 0;
|
| 98 |
+
let hoverEnd = 0;
|
| 99 |
+
let lastPage = 0;
|
| 100 |
+
|
| 101 |
+
function enableHover(pageId) {
|
| 102 |
+
for (let i = 1; i < a.length; i++) {
|
| 103 |
+
if (absoID(i) == pageId) {
|
| 104 |
+
a[i].classList.add("hover");
|
| 105 |
+
}
|
| 106 |
+
setTimeout(function() {
|
| 107 |
+
for (let j = 1; j < a.length; j++) {
|
| 108 |
+
a[j].classList.remove("hover");
|
| 109 |
+
}
|
| 110 |
+
}, hoverOutTimeout);
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
function disableHover(pageId) {
|
| 115 |
+
for (let i = 1; i < a.length; i++) {
|
| 116 |
+
if (absoID(i) == pageId) {
|
| 117 |
+
a[i].classList.remove("hover");
|
| 118 |
+
}
|
| 119 |
+
setTimeout(function() {
|
| 120 |
+
for (let j = 1; j < a.length; j++) {
|
| 121 |
+
a[j].classList.remove("hover");
|
| 122 |
+
}
|
| 123 |
+
}, hoverOutTimeout);
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
function absoID(pageId) {
|
| 128 |
+
return pageId * -1;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
const clickEventHandler = function(event) {
|
| 132 |
+
event.preventDefault();
|
| 133 |
+
event.stopPropagation();
|
| 134 |
+
const pageId = event.target.id.replace(/[^0-9]/g, "");
|
| 135 |
+
if (pageId) {
|
| 136 |
+
lastPage = pageId;
|
| 137 |
+
updatePage(pageId, zoom);
|
| 138 |
+
}
|
| 139 |
+
};
|
| 140 |
+
|
| 141 |
+
const hoverInEventHandler = function(event) {
|
| 142 |
+
event.preventDefault();
|
| 143 |
+
event.stopPropagation();
|
| 144 |
+
const pageId = event.target.id.replace(/[^0-9]/g, "");
|
| 145 |
+
if (pageId) {
|
| 146 |
+
lastPage = pageId;
|
| 147 |
+
enableHover(pageId);
|
| 148 |
+
}
|
| 149 |
+
};
|
| 150 |
+
|
| 151 |
+
const hoverOutEventHandler = function(event) {
|
| 152 |
+
event.preventDefault();
|
| 153 |
+
event.stopPropagation();
|
| 154 |
+
const pageId = event.target.id.replace(/[^0-9]/g, "");
|
| 155 |
+
if (pageId) {
|
| 156 |
+
lastPage = pageId;
|
| 157 |
+
disableHover(pageId);
|
| 158 |
+
}
|
| 159 |
+
};
|
| 160 |
+
|
| 161 |
+
this.on("mousemove", function(event) {
|
| 162 |
+
const x = event.clientX;
|
| 163 |
+
const y = event.clientY;
|
| 164 |
+
const pageId = Math.ceil(x / (width + 1)) + 1;
|
| 165 |
+
if (pageId && (pageId != lastPage && x >= 0 && x <= width && y >= 0 && y <= height)) {
|
| 166 |
+
console.log(pageId);
|
| 167 |
+
lastPage = pageId;
|
| 168 |
+
updatePage(pageId, zoom);
|
| 169 |
+
updateView(pageId);
|
| 170 |
+
}
|
| 171 |
+
});
|
| 172 |
+
|
| 173 |
+
function updatePage(pageId, zoom = 1) {
|
| 174 |
+
document.getElementById("page" + pageId).classList.add("page-active");
|
| 175 |
+
//check if page is not the current page
|
| 176 |
+
if (pageId != current_page) {
|
| 177 |
+
document.getElementById("page" + pageId).className = document.getElementById("page" + pageId).className.replace(/ ?page-(blank|active)/g, "");
|
| 178 |
+
updateView(pageId);
|
| 179 |
+
return;
|
| 180 |
+
}
|
| 181 |
+
if (zoom == 1) {
|
| 182 |
+
updateView(pageId);
|
| 183 |
+
return;
|
| 184 |
+
}
|
| 185 |
+
context.page = pageId;
|
| 186 |
+
context.zoom = zoom;
|
| 187 |
+
Object.assign(context.uniforms, UNIFORMS);
|
| 188 |
+
fluid.render();
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
function updateView(page) {
|
| 192 |
+
const material = new THREE.PDFMaterial(this.PDF_URL, light, new THREE.LinearFilter(THREE.WrapMode.REPEAT, THREE.WrapMode.REPEAT));
|
| 193 |
+
|
| 194 |
+
const timeline = document.getElementById(" timeline");
|
| 195 |
+
control.time.time.connect(timeline.timeRange);
|
| 196 |
+
|
| 197 |
+
const light = new THREE.JILLigSecurityLED();
|
| 198 |
+
light.position.set(0, 0, 0);
|
| 199 |
+
|
| 200 |
+
const mesh = new THREE.Mesh(THREE.PDFGeometry(this.pages[page - 1]), material);
|
| 201 |
+
|
| 202 |
+
const context = {
|
| 203 |
+
width: width,
|
| 204 |
+
height: height,
|
| 205 |
+
pdf_url: this.PDF_URL,
|
| 206 |
+
page: page,
|
| 207 |
+
zoom: zoom,
|
| 208 |
+
eventDispatcher: new THREE.EventDispatcher()
|
| 209 |
+
};
|
| 210 |
+
|
| 211 |
+
const frame = new THREE.PDFFrame(material, context);
|
| 212 |
+
frame.visible = frame.isVisible(page, zoom);
|
| 213 |
+
|
| 214 |
+
const fluid = new THREE.PDFFluidRender(context);
|
| 215 |
+
|
| 216 |
+
fluid.setFrame(frame);
|
| 217 |
+
scene.add(frame);
|
| 218 |
+
};
|
| 219 |
+
|
| 220 |
+
let startTime = null;
|
| 221 |
+
|
| 222 |
+
function animate() {
|
| 223 |
+
requestAnimationFrame(animate);
|
| 224 |
+
|
| 225 |
+
if (startTime === null) {
|
| 226 |
+
startTime = now();
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
const time = (now() - startTime) / 1000;
|
| 230 |
+
|
| 231 |
+
if (Math.abs(time - lastCallTime) >= 1000) {
|
| 232 |
+
lastCallTime = time;
|
| 233 |
+
console.log(time + " seconds");
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
// Only update the view more than 50 times a second
|
| 237 |
+
if ((now() - requestUpdateTime) / 1000 > 1000) {
|
| 238 |
+
context.timeBundle.time = time;
|
| 239 |
+
context.timeBundle.sqrti = Math.sqrt(zoom);
|
| 240 |
+
context.timeBundle.type = Math.floor(zoom);
|
| 241 |
+
context.timeBundle.time.ission = now() / 1000;
|
| 242 |
+
for (let i = 1; i < a.length; i++) {
|
| 243 |
+
a[i].style.setProperty("--page-vrp", absoID(i) + "px");
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
requestUpdateTime = now();
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
fluid.render();
|
| 250 |
+
}
|
| 251 |
+
animate();
|
| 252 |
+
</script>
|