File size: 3,209 Bytes
8ac3a87
 
 
 
08e6637
8ac3a87
 
 
 
c81c490
8ac3a87
898cc4c
8ac3a87
898cc4c
8ac3a87
 
898cc4c
8ac3a87
 
08e6637
 
 
 
8ac3a87
 
 
08e6637
8ac3a87
 
 
 
 
 
 
 
 
 
 
08e6637
 
8ac3a87
 
 
 
 
 
 
 
 
 
 
08e6637
 
 
8ac3a87
 
 
 
 
 
 
 
08e6637
 
 
8ac3a87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
08e6637
82e2b16
 
08e6637
 
8ac3a87
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# app.py
#
# Hugging Face Spaces  ➜  Build type: "FastAPI" (Python)
# μ‹€ν–‰ μ‹œ http://<space-url>/ 둜 μ ‘μ†ν•˜λ©΄ FlipBook UIκ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
import pathlib

BASE = pathlib.Path(__file__).parent

app = FastAPI()

# ── 1. 같은 ν΄λ”μ˜ 정적 파일(js / css / img / mp3 λ“±)을  /static  경둜둜 μ„œλΉ™
app.mount("/static", StaticFiles(directory=BASE), name="static")

# ── 2. index.html μ†ŒμŠ€ (script/link 경둜만 /static/ 둜 λ°”κΏˆ)
INDEX_HTML = """
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>FlipBook – μ—…λ‘œλ“œ + λ‚΄μž₯ μ‚¬μš΄λ“œ</title>

<link rel="stylesheet" href="/static/flipbook.css">

<!-- ν•„μˆ˜ JS μˆœμ„œ -->
<script src="/static/three.js"></script>
<script src="/static/iscroll.js"></script>
<script src="/static/mark.js"></script>
<script src="/static/mod3d.js"></script>

<script src="/static/flipbook.js"></script>
<script src="/static/flipbook.book3.js"></script>
<script src="/static/flipbook.scroll.js"></script>
<script src="/static/flipbook.swipe.js"></script>
<script src="/static/flipbook.webgl.js"></script>

<style>
 body{margin:0;font-family:sans-serif;background:#f4f4f4}
 h1{text-align:center;margin:24px 0}
 #viewer{width:900px;height:600px;margin:0 auto 40px;background:#fff;border:1px solid #ccc}
 .upload-wrapper{display:flex;justify-content:center}
 #uploadBtn{
   all:unset;width:44px;height:44px;line-height:44px;text-align:center;
   font-size:26px;border-radius:50%;cursor:pointer;
   background:#ffb84d;color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.2);transition:.2s;
 }
 #uploadBtn:hover{transform:translateY(-2px);box-shadow:0 4px 8px rgba(0,0,0,.25)}
 #fileInput{display:none}
</style>
</head>
<body>

<h1>Real3D FlipBook – 이미지 μ—…λ‘œλ“œ + μ‚¬μš΄λ“œ ✨</h1>

<div id="viewer"></div>

<div class="upload-wrapper">
  <button id="uploadBtn" title="이미지 μ—…λ‘œλ“œ">πŸ“·</button>
  <input id="fileInput" type="file" accept="image/*" multiple />
</div>

<script>
let book=null;
const holder=document.getElementById('viewer');

document.getElementById('uploadBtn').onclick=()=>document.getElementById('fileInput').click();

document.getElementById('fileInput').onchange=e=>{
  if(!e.target.files.length) return;
  const files=[...e.target.files];
  const pages=[];
  let done=0;
  files.forEach((f,i)=>{
    const rd=new FileReader();
    rd.onload=ev=>{
      pages[i]={src:ev.target.result,thumb:ev.target.result};
      if(++done===files.length) createBook(pages);
    };
    rd.readAsDataURL(f);
  });
};

function createBook(pages){
  if(book){ book.destroy(); holder.innerHTML=''; }

  book=new FlipBook(holder,{
    pages,
    viewMode:'webgl',
    autoSize:true,
    flipDuration:800,
    backgroundColor:'#ffffff',

    sound:true,
    assets:{
      flipMp3:'/static/turnPage2.mp3',
      hardFlipMp3:'/static/turnPage2.mp3'
    },

    controlsProps:{enableFullscreen:true,thumbnails:true}
  });
}
</script>
</body>
</html>
"""

# ── 3. λΌμš°ν„°:  GET /  β†’  index.html λ°˜ν™˜
@app.get("/", response_class=HTMLResponse)
async def root():
    return INDEX_HTML