|
|
import { html } from "https://cdn.skypack.dev/pin/htm@v3.2.2-nao32m88/mode=imports,min/optimized/htm.js"; |
|
|
import "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"; |
|
|
import { AlpineSome } from "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"; |
|
|
|
|
|
const PDF_FILE_URL1 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/material.pdf"; |
|
|
const PDF_FILE_URL2 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/newspaper.pdf"; |
|
|
const PDF_FILE_URL3 = "https://raw.githubusercontent.com/Pando85/real-time-rendering-PDF-viewer/master/docs/plane.pdf"; |
|
|
|
|
|
const pdfCatalog = {}; |
|
|
|
|
|
class PDFViewer { |
|
|
constructor(file_url, pdfDocument) { |
|
|
this.file_url = file_url; |
|
|
this.pdfDocument = pdfDocument; |
|
|
this.pages = pdfDocument.pages; |
|
|
this.current_page = 0; |
|
|
this.zoom = 1; |
|
|
} |
|
|
|
|
|
updatePage(current_page = 1, zoom = 1) { |
|
|
if (current_page < 0) { |
|
|
current_page = 1; |
|
|
} else if (current_page > this.pages.length) { |
|
|
current_page = this.pages.length; |
|
|
} |
|
|
|
|
|
this.current_page = current_page; |
|
|
this.zoom = zoom; |
|
|
} |
|
|
|
|
|
render() { |
|
|
this.disablePreviewPage(); |
|
|
|
|
|
const width = this.pages[0].getWidth(); |
|
|
const height = this.pages[0].getHeight(); |
|
|
|
|
|
const viewport = new THREE.PDFViewerViewport(width, height, this.zoom); |
|
|
|
|
|
const scene = new THREE.Scene(); |
|
|
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000); |
|
|
|
|
|
const uniforms = new THREE.PDFUniforms(UNIFORMS.TIME, UNIFORMS.RESOLUTION); |
|
|
const control = new THREE.OrbitalControl(); |
|
|
camera.userData.JZBody = new THREE.TVCameraJz Mangn(control, uniforms); |
|
|
|
|
|
const timeline = document.getElementById(" timeline"); |
|
|
control.time.time.connect(timeline.timeRange); |
|
|
|
|
|
const light = new THREE.JILLigSecurityLED(); |
|
|
light.position.set(0, 0, 0); |
|
|
|
|
|
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))); |
|
|
|
|
|
let mesh; |
|
|
for (let i = 1; i < this.pages.length; i++) { |
|
|
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))); |
|
|
mesh.position.set(width * i / 100, 0, 0); |
|
|
scene.add(mesh); |
|
|
} |
|
|
|
|
|
const context = { |
|
|
width: width, |
|
|
height: height, |
|
|
pdf_url: this.PDF_URL, |
|
|
page: this.current_page + 1, |
|
|
zoom: this.zoom, |
|
|
eventDispatcher: new THREE.EventDispatcher() |
|
|
}; |
|
|
|
|
|
const loader = new THREE.PDFLoader(); |
|
|
loader.load(); |
|
|
|
|
|
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>"); |
|
|
document.body.appendChild(ref.content); |
|
|
|
|
|
for (let i = 1; i < this.pages.length; i++) { |
|
|
const page_data = this.pages[i]; |
|
|
const page_el = document.createElement("div"); |
|
|
page_el.id = "page" + (i + 1); |
|
|
page_e.classList.add("page-box"); |
|
|
page_e.innerHTML = page_data; |
|
|
ref.content.appendChild(page_el); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const a = Alpine.document.querySelectorAll("#main .page"); |
|
|
for (let i = 1; i < a.length; i++) { |
|
|
a[i].setAttribute("style", "transition-duration: 0s"); |
|
|
} |
|
|
|
|
|
const hoverOffset = 20; |
|
|
const hoverRange = 3; |
|
|
const hoverInTimeout = 200; |
|
|
const hoverOutTimeout = 200; |
|
|
let hoverNotFound = 0; |
|
|
let hoverStart = 0; |
|
|
let hoverEnd = 0; |
|
|
let lastPage = 0; |
|
|
|
|
|
function enableHover(pageId) { |
|
|
for (let i = 1; i < a.length; i++) { |
|
|
if (absoID(i) == pageId) { |
|
|
a[i].classList.add("hover"); |
|
|
} |
|
|
setTimeout(function() { |
|
|
for (let j = 1; j < a.length; j++) { |
|
|
a[j].classList.remove("hover"); |
|
|
} |
|
|
}, hoverOutTimeout); |
|
|
} |
|
|
} |
|
|
|
|
|
function disableHover(pageId) { |
|
|
for (let i = 1; i < a.length; i++) { |
|
|
if (absoID(i) == pageId) { |
|
|
a[i].classList.remove("hover"); |
|
|
} |
|
|
setTimeout(function() { |
|
|
for (let j = 1; j < a.length; j++) { |
|
|
a[j].classList.remove("hover"); |
|
|
} |
|
|
}, hoverOutTimeout); |
|
|
} |
|
|
} |
|
|
|
|
|
function absoID(pageId) { |
|
|
return pageId * -1; |
|
|
} |
|
|
|
|
|
const clickEventHandler = function(event) { |
|
|
event.preventDefault(); |
|
|
event.stopPropagation(); |
|
|
const pageId = event.target.id.replace(/[^0-9]/g, ""); |
|
|
if (pageId) { |
|
|
lastPage = pageId; |
|
|
updatePage(pageId, zoom); |
|
|
} |
|
|
}; |
|
|
|
|
|
const hoverInEventHandler = function(event) { |
|
|
event.preventDefault(); |
|
|
event.stopPropagation(); |
|
|
const pageId = event.target.id.replace(/[^0-9]/g, ""); |
|
|
if (pageId) { |
|
|
lastPage = pageId; |
|
|
enableHover(pageId); |
|
|
} |
|
|
}; |
|
|
|
|
|
const hoverOutEventHandler = function(event) { |
|
|
event.preventDefault(); |
|
|
event.stopPropagation(); |
|
|
const pageId = event.target.id.replace(/[^0-9]/g, ""); |
|
|
if (pageId) { |
|
|
lastPage = pageId; |
|
|
disableHover(pageId); |
|
|
} |
|
|
}; |
|
|
|
|
|
this.on("mousemove", function(event) { |
|
|
const x = event.clientX; |
|
|
const y = event.clientY; |
|
|
const pageId = Math.ceil(x / (width + 1)) + 1; |
|
|
if (pageId && (pageId != lastPage && x >= 0 && x <= width && y >= 0 && y <= height)) { |
|
|
console.log(pageId); |
|
|
lastPage = pageId; |
|
|
updatePage(pageId, zoom); |
|
|
updateView(pageId); |
|
|
} |
|
|
}); |
|
|
|
|
|
function updatePage(pageId, zoom = 1) { |
|
|
document.getElementById("page" + pageId).classList.add("page-active"); |
|
|
|
|
|
if (pageId != current_page) { |
|
|
document.getElementById("page" + pageId).className = document.getElementById("page" + pageId).className.replace(/ ?page-(blank|active)/g, ""); |
|
|
updateView(pageId); |
|
|
return; |
|
|
} |
|
|
if (zoom == 1) { |
|
|
updateView(pageId); |
|
|
return; |
|
|
} |
|
|
context.page = pageId; |
|
|
context.zoom = zoom; |
|
|
Object.assign(context.uniforms, UNIFORMS); |
|
|
fluid.render(); |
|
|
} |
|
|
|
|
|
function updateView(page) { |
|
|
const material = new THREE.PDFMaterial(this.PDF_URL, light, new THREE.LinearFilter(THREE.WrapMode.REPEAT, THREE.WrapMode.REPEAT)); |
|
|
|
|
|
const timeline = document.getElementById(" timeline"); |
|
|
control.time.time.connect(timeline.timeRange); |
|
|
|
|
|
const light = new THREE.JILLigSecurityLED(); |
|
|
light.position.set(0, 0, 0); |
|
|
|
|
|
const mesh = new THREE.Mesh(THREE.PDFGeometry(this.pages[page - 1]), material); |
|
|
|
|
|
const context = { |
|
|
width: width, |
|
|
height: height, |
|
|
pdf_url: this.PDF_URL, |
|
|
page: page, |
|
|
zoom: zoom, |
|
|
eventDispatcher: new THREE.EventDispatcher() |
|
|
}; |
|
|
|
|
|
const frame = new THREE.PDFFrame(material, context); |
|
|
frame.visible = frame.isVisible(page, zoom); |
|
|
|
|
|
const fluid = new THREE.PDFFluidRender(context); |
|
|
|
|
|
fluid.setFrame(frame); |
|
|
scene.add(frame); |
|
|
}; |
|
|
|
|
|
let startTime = null; |
|
|
|
|
|
function animate() { |
|
|
requestAnimationFrame(animate); |
|
|
|
|
|
if (startTime === null) { |
|
|
startTime = now(); |
|
|
} |
|
|
|
|
|
const time = (now() - startTime) / 1000; |
|
|
|
|
|
if (Math.abs(time - lastCallTime) >= 1000) { |
|
|
lastCallTime = time; |
|
|
console.log(time + " seconds"); |
|
|
} |
|
|
|
|
|
|
|
|
if ((now() - requestUpdateTime) / 1000 > 1000) { |
|
|
context.timeBundle.time = time; |
|
|
context.timeBundle.sqrti = Math.sqrt(zoom); |
|
|
context.timeBundle.type = Math.floor(zoom); |
|
|
context.timeBundle.time.ission = now() / 1000; |
|
|
for (let i = 1; i < a.length; i++) { |
|
|
a[i].style.setProperty("--page-vrp", absoID(i) + "px"); |
|
|
} |
|
|
|
|
|
requestUpdateTime = now(); |
|
|
} |
|
|
|
|
|
fluid.render(); |
|
|
} |
|
|
animate(); |
|
|
</script> |