Ronaldo1111 commited on
Commit
126efab
·
verified ·
1 Parent(s): 07cf1d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -73
app.py CHANGED
@@ -180,7 +180,8 @@ def chat(user_input, history):
180
 
181
  import gradio as gr
182
 
183
- # ==== 静态资源 ====
 
184
  background_images = [
185
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family.jpg",
186
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family1.jpg",
@@ -193,51 +194,45 @@ background_images = [
193
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family8.jpg",
194
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family9.jpg"
195
  ]
196
- background_css = "".join([
197
- f"{i * 10}% {{ background-image: url({img}); }}\n"
198
- for i, img in enumerate(background_images)
199
  ])
 
 
200
  avatar_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/bean.jpg"
201
  cake_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/birthday.jpg"
202
  music1 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/FNG.mp3"
203
  music2 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/PGY.mp3"
204
  bark_sound = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/voice.mp3"
205
 
206
- # ==== Gradio 页面构建 ====
207
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
208
- gr.Markdown("## 🌸 Horse and 7 Agent:欢迎进入豌豆的世界 🌸")
209
-
210
- chatbot = gr.Chatbot(label="Horse and 7", type="messages", show_copy_button=True)
211
- msg = gr.Textbox(label="想对豌豆说啥?", placeholder="比如:你在干嘛?", lines=2)
212
- btn = gr.Button("投喂")
213
-
214
- html_content = f"""
215
  <style>
216
- body {{
217
  margin: 0;
218
  animation: backgroundCycle 60s infinite;
219
  background-size: cover;
220
  background-position: center;
221
  transition: background-image 1s ease-in-out;
222
- }}
223
- @keyframes backgroundCycle {{
224
- {background_css}
225
- }}
226
- .gr-chatbot {{
227
  background: rgba(255, 255, 255, 0.5);
228
  border-radius: 16px;
229
  padding: 10px;
230
- }}
231
- .gr-textbox textarea {{
232
  font-family: monospace;
233
  font-size: 1.1em;
234
  animation: typewriter 1s steps(40, end);
235
- }}
236
- @keyframes typewriter {{
237
- from {{ width: 0 }}
238
- to {{ width: 100% }}
239
- }}
240
- #sophia-avatar {{
241
  position: fixed;
242
  top: 40px;
243
  left: 30px;
@@ -247,28 +242,27 @@ html_content = f"""
247
  z-index: 9999;
248
  cursor: grab;
249
  animation: spinBounce 4s infinite;
250
- }}
251
- @keyframes spinBounce {{
252
- 0% {{ transform: rotate(0deg) translateY(0px); }}
253
- 50% {{ transform: rotate(180deg) translateY(-10px); }}
254
- 100% {{ transform: rotate(360deg) translateY(0px); }}
255
- }}
256
- #birthday-cake {{
257
  position: fixed;
258
  bottom: 20px;
259
  right: 20px;
260
  width: 80px;
261
  animation: bounce 1.5s infinite;
262
  z-index: 9999;
263
- }}
264
- @keyframes bounce {{
265
- 0% {{ transform: translateY(0); }}
266
- 50% {{ transform: translateY(-15px); }}
267
- 100% {{ transform: translateY(0); }}
268
- }}
269
  </style>
270
 
271
- <!-- 动态头像 + 生日蛋糕 -->
272
  <img id="sophia-avatar" src="{avatar_url}" />
273
  <img id="birthday-cake" src="{cake_url}" />
274
  <audio id="bg-music" autoplay loop>
@@ -279,64 +273,81 @@ html_content = f"""
279
  <canvas id="fireworks" style="position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:0;"></canvas>
280
 
281
  <script>
 
282
  const tracks = ["{music1}", "{music2}"];
283
  const audio = document.getElementById("bg-music");
284
  let current = 0;
285
- audio.addEventListener("ended", () => {{
286
  current = (current + 1) % tracks.length;
287
  audio.src = tracks[current];
288
- audio.play();
289
- }});
290
 
 
291
  const avatar = document.getElementById("sophia-avatar");
292
- avatar.onmousedown = function(e) {{
 
293
  const shiftX = e.clientX - avatar.getBoundingClientRect().left;
294
  const shiftY = e.clientY - avatar.getBoundingClientRect().top;
295
- function moveAt(e) {{
296
  avatar.style.left = e.pageX - shiftX + 'px';
297
  avatar.style.top = e.pageY - shiftY + 'px';
298
- }}
299
  document.addEventListener('mousemove', moveAt);
300
- avatar.onmouseup = function() {{
301
  document.removeEventListener('mousemove', moveAt);
302
  avatar.onmouseup = null;
303
- }};
304
- }};
305
  avatar.ondragstart = () => false;
306
- avatar.addEventListener("click", () => {{
307
- document.getElementById("bark").play();
308
- }});
309
 
 
310
  const canvas = document.getElementById("fireworks");
311
  const ctx = canvas.getContext("2d");
312
- canvas.width = window.innerWidth;
313
- canvas.height = window.innerHeight;
314
-
315
- function firework() {{
316
  const x = Math.random() * canvas.width;
317
  const y = Math.random() * canvas.height;
318
- for (let i = 0; i < 30; i++) {{
319
- setTimeout(() => {{
320
  ctx.beginPath();
321
  ctx.arc(x, y, Math.random() * 3 + 2, 0, Math.PI * 2);
322
  ctx.fillStyle = 'hsl(' + (Math.random() * 360) + ', 100%, 60%)';
323
  ctx.fill();
324
- }}, i * 20);
325
- }}
326
- }}
327
-
328
  setInterval(firework, 1800);
329
  </script>
330
- """
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
- html_content = html_content.replace("{background_css}", background_css)
334
- html_content = html_content.replace("{avatar_url}", avatar_url)
335
- html_content = html_content.replace("{cake_url}", cake_url)
336
- html_content = html_content.replace("{music1}", music1)
337
- html_content = html_content.replace("{music2}", music2)
338
- html_content = html_content.replace("{bark_sound}", bark_sound)
339
 
340
-
341
- gr.HTML(html_content)
342
- demo.launch()
 
180
 
181
  import gradio as gr
182
 
183
+
184
+ # ==== 静态资源 ====
185
  background_images = [
186
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family.jpg",
187
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family1.jpg",
 
194
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family8.jpg",
195
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family9.jpg"
196
  ]
197
+ # 生成 background keyframes
198
+ background_css_rules = "".join([
199
+ f" {i * 10}% {{ background-image: url('{img}'); }}\n" for i, img in enumerate(background_images)
200
  ])
201
+ background_css = f"@keyframes backgroundCycle {{\n{background_css_rules}}}"
202
+
203
  avatar_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/bean.jpg"
204
  cake_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/birthday.jpg"
205
  music1 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/FNG.mp3"
206
  music2 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/PGY.mp3"
207
  bark_sound = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/voice.mp3"
208
 
209
+ # ==== HTML/CSS/JS 模板(使用 .replace 安全插值) ====
210
+ html_template = '''
 
 
 
 
 
 
 
211
  <style>
212
+ body {
213
  margin: 0;
214
  animation: backgroundCycle 60s infinite;
215
  background-size: cover;
216
  background-position: center;
217
  transition: background-image 1s ease-in-out;
218
+ }
219
+ {background_css}
220
+
221
+ .gr-chatbot {
 
222
  background: rgba(255, 255, 255, 0.5);
223
  border-radius: 16px;
224
  padding: 10px;
225
+ }
226
+ .gr-textbox textarea {
227
  font-family: monospace;
228
  font-size: 1.1em;
229
  animation: typewriter 1s steps(40, end);
230
+ }
231
+ @keyframes typewriter {
232
+ from { width: 0 }
233
+ to { width: 100% }
234
+ }
235
+ #sophia-avatar {
236
  position: fixed;
237
  top: 40px;
238
  left: 30px;
 
242
  z-index: 9999;
243
  cursor: grab;
244
  animation: spinBounce 4s infinite;
245
+ }
246
+ @keyframes spinBounce {
247
+ 0% { transform: rotate(0deg) translateY(0); }
248
+ 50% { transform: rotate(180deg) translateY(-10px); }
249
+ 100% { transform: rotate(360deg) translateY(0); }
250
+ }
251
+ #birthday-cake {
252
  position: fixed;
253
  bottom: 20px;
254
  right: 20px;
255
  width: 80px;
256
  animation: bounce 1.5s infinite;
257
  z-index: 9999;
258
+ }
259
+ @keyframes bounce {
260
+ 0% { transform: translateY(0); }
261
+ 50% { transform: translateY(-15px); }
262
+ 100% { transform: translateY(0); }
263
+ }
264
  </style>
265
 
 
266
  <img id="sophia-avatar" src="{avatar_url}" />
267
  <img id="birthday-cake" src="{cake_url}" />
268
  <audio id="bg-music" autoplay loop>
 
273
  <canvas id="fireworks" style="position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:0;"></canvas>
274
 
275
  <script>
276
+ // 背景音乐轮播
277
  const tracks = ["{music1}", "{music2}"];
278
  const audio = document.getElementById("bg-music");
279
  let current = 0;
280
+ audio.addEventListener("ended", () => {
281
  current = (current + 1) % tracks.length;
282
  audio.src = tracks[current];
283
+ audio.load(); audio.play();
284
+ });
285
 
286
+ // 头像拖拽 & Bark 音效
287
  const avatar = document.getElementById("sophia-avatar");
288
+ const bark = document.getElementById("bark");
289
+ avatar.onmousedown = function(e) {
290
  const shiftX = e.clientX - avatar.getBoundingClientRect().left;
291
  const shiftY = e.clientY - avatar.getBoundingClientRect().top;
292
+ function moveAt(e) {
293
  avatar.style.left = e.pageX - shiftX + 'px';
294
  avatar.style.top = e.pageY - shiftY + 'px';
295
+ }
296
  document.addEventListener('mousemove', moveAt);
297
+ avatar.onmouseup = function() {
298
  document.removeEventListener('mousemove', moveAt);
299
  avatar.onmouseup = null;
300
+ };
301
+ };
302
  avatar.ondragstart = () => false;
303
+ avatar.addEventListener("click", () => {
304
+ bark.pause(); bark.currentTime = 0; bark.play();
305
+ });
306
 
307
+ // 简易烟花特效
308
  const canvas = document.getElementById("fireworks");
309
  const ctx = canvas.getContext("2d");
310
+ canvas.width = window.innerWidth; canvas.height = window.innerHeight;
311
+ function firework() {
 
 
312
  const x = Math.random() * canvas.width;
313
  const y = Math.random() * canvas.height;
314
+ for (let i = 0; i < 30; i++) {
315
+ setTimeout(() => {
316
  ctx.beginPath();
317
  ctx.arc(x, y, Math.random() * 3 + 2, 0, Math.PI * 2);
318
  ctx.fillStyle = 'hsl(' + (Math.random() * 360) + ', 100%, 60%)';
319
  ctx.fill();
320
+ }, i * 20);
321
+ }
322
+ }
 
323
  setInterval(firework, 1800);
324
  </script>
325
+ '''
326
 
327
+ # 安全插值
328
+ html_content = html_template.replace("{background_css}", background_css) \
329
+ .replace("{avatar_url}", avatar_url) \
330
+ .replace("{cake_url}", cake_url) \
331
+ .replace("{music1}", music1) \
332
+ .replace("{music2}", music2) \
333
+ .replace("{bark_sound}", bark_sound)
334
+
335
+ # ==== Gradio 界面 ====
336
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
337
+ # 注入自定义样式和脚本,必须放在最前
338
+ gr.HTML(html_content)
339
+
340
+ # 标题和聊天组件
341
+ gr.Markdown("## 🌸 Horse and 7 Agent:欢迎进入豌豆的世界 🌸")
342
+ chatbot = gr.Chatbot(label="Sophia", type="messages", show_copy_button=True)
343
+ msg = gr.Textbox(label="想对豌豆说啥?", placeholder="比如:你在干嘛?", lines=2)
344
+ state = gr.State([])
345
+ btn = gr.Button("投喂")
346
 
347
+ # 绑定聊天函数
348
+ btn.click(chat, inputs=[msg, state], outputs=[chatbot, state])
349
+ msg.submit(chat, inputs=[msg, state], outputs=[chatbot, state])
 
 
 
350
 
351
+ # 启动
352
+ if __name__ == "__main__":
353
+ demo.launch()