Spaces:
Running
Running
| <html lang="ro"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Cititor</title> | |
| <style> | |
| body { | |
| margin: 0; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| height: 100vh; | |
| background-color: #f5f5f5; | |
| overflow: hidden; | |
| } | |
| #reader-container { | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| overflow: hidden; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| #reader-container img { | |
| width: 100%; | |
| height: auto; | |
| transform-origin: center center; | |
| transition: transform 0.3s; | |
| cursor: grab; | |
| } | |
| @media (min-width: 768px) { | |
| #reader-container img { | |
| height: 90vh; | |
| width: auto; | |
| } | |
| } | |
| .controls { | |
| position: absolute; | |
| bottom: 20px; | |
| display: flex; | |
| justify-content: center; | |
| gap: 10px; | |
| } | |
| button { | |
| padding: 10px 20px; | |
| font-size: 16px; | |
| cursor: pointer; | |
| border: none; | |
| border-radius: 5px; | |
| background-color: #007bff; | |
| color: white; | |
| transition: background-color 0.3s; | |
| } | |
| button:disabled { | |
| background-color: #ddd; | |
| cursor: not-allowed; | |
| } | |
| button:hover:not(:disabled) { | |
| background-color: #0056b3; | |
| } | |
| #page-input { | |
| position: absolute; | |
| top: 20px; | |
| font-size: 24px; | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 10px; | |
| text-align: center; | |
| z-index: 1; | |
| width: 190px; | |
| @media (orientation: portrait) { | |
| transform: translate(30px, 0px); | |
| } | |
| } | |
| #page-input:focus { | |
| outline: none; | |
| box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); | |
| } | |
| #page-number { | |
| position: absolute; | |
| top: 20px; | |
| left: 20px; | |
| font-size: 24px; | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 10px; | |
| text-align: center; | |
| z-index: 1; | |
| background-color: #007bff; | |
| color: white; | |
| } | |
| #loading-message { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| font-size: 24px; | |
| color: #333; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="reader-container"> | |
| <div id="page-number"></div> | |
| <input id="page-input" type="number" placeholder="Introdu pagina" oninput="handlePageInput(this.value)"> | |
| <img id="page-image" src="pages/1.jpg" alt="Pagina 1" style="display: none;"> | |
| <div id="loading-message">Imaginea se încarcă, vă rog așteptați</div> | |
| </div> | |
| <div class="controls"> | |
| <button id="prev-button" disabled>Înapoi</button> | |
| <button id="next-button">Înainte</button> | |
| </div> | |
| <script> | |
| const TOTAL_PAGES = 92; | |
| let currentPage = 1; | |
| const imageElement = document.getElementById('page-image'); | |
| const prevButton = document.getElementById('prev-button'); | |
| const nextButton = document.getElementById('next-button'); | |
| const pageNumberElement = document.getElementById('page-number'); | |
| const loadingMessage = document.getElementById('loading-message'); | |
| const updatePage = () => { | |
| imageElement.src = `pages/${currentPage}.jpg`; | |
| imageElement.alt = `Pagina ${currentPage}`; | |
| prevButton.disabled = currentPage === 1; | |
| nextButton.disabled = currentPage === TOTAL_PAGES; | |
| const pageNumber = currentPage * 2 + 1; | |
| pageNumberElement.textContent = `${pageNumber - 1}-${pageNumber}`; | |
| imageElement.style.display = 'none'; | |
| loadingMessage.style.display = 'block'; | |
| }; | |
| imageElement.onload = () => { | |
| imageElement.style.display = 'block'; | |
| loadingMessage.style.display = 'none'; | |
| }; | |
| prevButton.addEventListener('click', () => { | |
| if (currentPage > 1) { | |
| currentPage--; | |
| updatePage(); | |
| } | |
| }); | |
| nextButton.addEventListener('click', () => { | |
| if (currentPage < TOTAL_PAGES) { | |
| currentPage++; | |
| updatePage(); | |
| } | |
| }); | |
| let scale = 1; | |
| const zoomStep = 0.1; | |
| const maxScale = 3; | |
| const minScale = 1; | |
| let translateX = 0; | |
| let translateY = 0; | |
| const zoom = (delta) => { | |
| scale = Math.min(maxScale, Math.max(minScale, scale + delta)); | |
| applyTransform(); | |
| }; | |
| const applyTransform = () => { | |
| imageElement.style.transform = `scale(${scale}) translate(${translateX}px, ${translateY}px)`; | |
| }; | |
| imageElement.addEventListener('wheel', (e) => { | |
| e.preventDefault(); | |
| zoom(e.deltaY < 0 ? zoomStep : -zoomStep); | |
| }); | |
| let startX = 0; | |
| let startY = 0; | |
| let isDragging = false; | |
| imageElement.addEventListener('mousedown', (e) => { | |
| e.preventDefault(); | |
| startX = e.clientX; | |
| startY = e.clientY; | |
| isDragging = true; | |
| imageElement.style.cursor = 'grabbing'; | |
| }); | |
| window.addEventListener('mousemove', (e) => { | |
| if (isDragging) { | |
| const dx = e.clientX - startX; | |
| const dy = e.clientY - startY; | |
| translateX += dx / scale; | |
| translateY += dy / scale; | |
| startX = e.clientX; | |
| startY = e.clientY; | |
| applyTransform(); | |
| } | |
| }); | |
| window.addEventListener('mouseup', () => { | |
| isDragging = false; | |
| imageElement.style.cursor = 'grab'; | |
| }); | |
| let touchStartDistance = 0; | |
| imageElement.addEventListener('touchstart', (e) => { | |
| if (e.touches.length === 2) { | |
| e.preventDefault(); | |
| touchStartDistance = Math.hypot( | |
| e.touches[0].clientX - e.touches[1].clientX, | |
| e.touches[0].clientY - e.touches[1].clientY | |
| ); | |
| } else if (e.touches.length === 1) { | |
| startX = e.touches[0].clientX; | |
| startY = e.touches[0].clientY; | |
| isDragging = true; | |
| } | |
| }); | |
| imageElement.addEventListener('touchmove', (e) => { | |
| if (e.touches.length === 2) { | |
| e.preventDefault(); | |
| const currentDistance = Math.hypot( | |
| e.touches[0].clientX - e.touches[1].clientX, | |
| e.touches[0].clientY - e.touches[1].clientY | |
| ); | |
| const delta = (currentDistance - touchStartDistance) / 100; | |
| zoom(delta); | |
| touchStartDistance = currentDistance; | |
| } else if (e.touches.length === 1 && isDragging) { | |
| e.preventDefault(); | |
| const dx = e.touches[0].clientX - startX; | |
| const dy = e.touches[0].clientY - startY; | |
| translateX += dx / scale; | |
| translateY += dy / scale; | |
| startX = e.touches[0].clientX; | |
| startY = e.touches[0].clientY; | |
| applyTransform(); | |
| } | |
| }); | |
| imageElement.addEventListener('touchend', () => { | |
| isDragging = false; | |
| }); | |
| function handlePageInput(value) { | |
| const pageNumber = parseInt(value); | |
| if (!isNaN(pageNumber)) { | |
| if (pageNumber % 2 === 0) { | |
| currentPage = pageNumber / 2; | |
| } else { | |
| currentPage = (pageNumber - 1) / 2; | |
| } | |
| updatePage(); | |
| } | |
| } | |
| updatePage(); | |
| </script> | |
| </body> | |
| </html> | |