Welcome to my Website!

This is a paragraph! Here's how you make a link: Neocities.

Here's how you can make bold and italic text.

Here's how you can add an image:

Site hosted by Neocities

Here's how to make a list:

To learn more HTML/CSS, check out these tutorials!

import React, { useState, useEffect, useRef } from "react"; // Single-file React component for an online picture-book reader // Usage: place your image files at /images/page0.jpg ... /images/page10.jpg (or png) // This component uses Tailwind CSS for styling. It's a self-contained page component // with keyboard navigation, swipe support, thumbnails, and a simple share/print control. const PAGES = [ { id: 0, title: "影子的假期", text: "早晨,小孩在草地上奔跑、踢球、畫畫,影子緊緊跟著每個動作。", img: "/images/page0.jpg", alt: "封面:夕陽操場與跳繩的影子" }, { id: 1, title: "", text: "小孩嘗試甩開影子——用手電筒照、跳來跳去、甚至拿紙蓋住地板。有時候,我只想一個人玩。", img: "/images/page1.jpg", alt: "小孩試圖甩開影子" }, { id: 2, title: "", text: "夜晚,月光照進房間,小孩熟睡。那天晚上,影子也這麼想。", img: "/images/page2.jpg", alt: "月光下窗邊熟睡的孩子與影子" }, { id: 3, title: "", text: "影子走出窗戶,街燈下的世界滿是影子:貓的影子、樹的影子、風箏的影子。『我要去旅行!』影子輕輕說。", img: "/images/page3.jpg", alt: "影子走出窗外,街燈與影子世界" }, { id: 4, title: "", text: "影子在城市裡旅行——牆上變成蝴蝶飛舞、在公車後面拉長成一條帶子、和路燈影子跳舞。", img: "/images/page4.jpg", alt: "城市裡影子與蝴蝶、公交拖影" }, { id: 5, title: "", text: "影子來到海邊。它想跳進水裡玩,但只浮在水面上,看見『自己不見了』。", img: "/images/page5.jpg", alt: "海邊浮在水面的影子" }, { id: 6, title: "", text: "夜晚,影子坐在石頭上,看著星空。星星的光讓它變得很淡、幾乎消失。", img: "/images/page6.jpg", alt: "石頭上看星空的影子" }, { id: 7, title: "", text: "影子跑回城市、越過街燈、爬上窗台。小孩醒來,看到牆上熟悉的形狀。", img: "/images/page7.jpg", alt: "影子跑回窗台,孩子醒來" }, { id: 8, title: "", text: "清晨的陽光裡,小孩與影子在地上一起做怪姿勢。影子學著他;他也學著影子。原來,有時分開,也能讓我們更靠近。", img: "/images/page8.jpg", alt: "清晨一起做怪姿勢的孩子與影子" }, { id: 9, title: "", text: "下一次假期,我們一起去。", img: "/images/page9.jpg", alt: "下一次假期我們一起去 — 結尾封底" }, { id: 10, title: "作者/製作資訊", text: "封底資訊或製作說明,可在此放置聯絡、版權或製作團隊資料。", img: "/images/page10.jpg", alt: "製作資訊封底" } ]; export default function StoryReader() { const [index, setIndex] = useState(0); const [showThumbnails, setShowThumbnails] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false); const containerRef = useRef(null); const touchStartX = useRef(0); const touchEndX = useRef(0); useEffect(() => { function onKey(e) { if (e.key === "ArrowRight") next(); if (e.key === "ArrowLeft") prev(); if (e.key === "f") toggleFullscreen(); } window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [index]); useEffect(() => { // prevent scroll when fullscreen document.body.style.overflow = isFullscreen ? "hidden" : ""; return () => { document.body.style.overflow = ""; }; }, [isFullscreen]); function next() { setIndex((i) => Math.min(i + 1, PAGES.length - 1)); } function prev() { setIndex((i) => Math.max(i - 1, 0)); } function goTo(i) { setIndex(i); setShowThumbnails(false); } function toggleFullscreen() { setIsFullscreen((v) => !v); } function onTouchStart(e) { touchStartX.current = e.touches[0].clientX; } function onTouchMove(e) { touchEndX.current = e.touches[0].clientX; } function onTouchEnd() { const dx = touchEndX.current - touchStartX.current; if (dx < -40) next(); if (dx > 40) prev(); } // Preload neighbor images for smoother navigation useEffect(() => { const nextIdx = Math.min(index + 1, PAGES.length - 1); const prevIdx = Math.max(index - 1, 0); [nextIdx, prevIdx].forEach((i) => { const img = new Image(); img.src = PAGES[i].img; }); }, [index]); return (

影子的假期 — 線上閱讀

{/* Left: image viewer */}
{PAGES[index].alt} {/* page number */}
{index + 1}/{PAGES.length}

{PAGES[index].text}

提示:使用 ← → 鍵切換,或在手機上左右滑動。按 f 切換全螢幕。
{/* Right: thumbnails / info */}
{/* thumbnails modal for small screens */} {showThumbnails && (
{PAGES.map((p, i) => ( ))}
)}
); }