Skip to content

Instantly share code, notes, and snippets.

@JSoon
Created July 2, 2025 05:13
Show Gist options
  • Save JSoon/523dab5ed340bbc093c941496d2aafd3 to your computer and use it in GitHub Desktop.
Save JSoon/523dab5ed340bbc093c941496d2aafd3 to your computer and use it in GitHub Desktop.
Flipbook Swipe Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Flipbook Swipe Example</title>
<!-- 引入animate.css -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
background: #fdf6e3;
font-family: Arial, sans-serif;
}
#flipbook {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
#flipbook>div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow-y: auto;
background: white;
padding: 20px;
box-sizing: border-box;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
transition: transform 0.4s ease, opacity 0.4s ease;
}
/* 初始隐藏所有页 */
#flipbook>div.hidden {
display: none;
}
/* 动画类 */
.enter-from-right {
transform: translateX(100%);
}
.enter-from-left {
transform: translateX(-100%);
}
.leave-to-left {
transform: translateX(-100%);
opacity: 0;
}
.leave-to-right {
transform: translateX(100%);
opacity: 0;
}
/* 标题动画样式 */
.page-title {
animation-duration: 0.8s;
}
</style>
</head>
<body>
<div id="flipbook">
<div>
<h2 class="page-title animate__animated animate__backInLeft">Page 1</h2>
<p>这是第一页内容。</p>
</div>
<div>
<h2 class="page-title animate__animated animate__backInLeft">Page 2</h2>
<p>这是第二页内容。上下滚动试试。</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
<p>内容内容内容内容内容</p>
</div>
<div>
<h2 class="page-title animate__animated animate__backInLeft">Page 3</h2>
<p>这是第三页内容。</p>
</div>
<div>
<h2 class="page-title animate__animated animate__backInLeft">Page 4</h2>
<p>这是第四页内容。</p>
</div>
</div>
<script>
const pages = Array.from(document.querySelectorAll('#flipbook > div'));
let currentIndex = 0;
// 初始化:只显示第一页
pages.forEach((page, index) => {
if (index !== 0) page.classList.add('hidden');
});
function showPage(newIndex, direction) {
if (newIndex < 0 || newIndex >= pages.length || newIndex === currentIndex) return;
const current = pages[currentIndex];
const next = pages[newIndex];
// 重置标题动画
const currentTitle = current.querySelector('.page-title');
const nextTitle = next.querySelector('.page-title');
// 设置初始进入方向
next.classList.remove('hidden');
next.classList.add(direction === 'next' ? 'enter-from-right' : 'enter-from-left');
// 强制触发一次重绘
next.offsetHeight;
// 开始动画
next.classList.remove('enter-from-right', 'enter-from-left');
current.classList.add(direction === 'next' ? 'leave-to-left' : 'leave-to-right');
setTimeout(() => {
current.classList.add('hidden');
current.classList.remove('leave-to-left', 'leave-to-right');
currentIndex = newIndex;
}, 400);
}
function goNext() {
if (currentIndex < pages.length - 1) {
showPage(currentIndex + 1, 'next');
}
}
function goPrev() {
if (currentIndex > 0) {
showPage(currentIndex - 1, 'prev');
}
}
// 手势检测
let startX = 0, startY = 0, isScrolling;
document.getElementById('flipbook').addEventListener('touchstart', function (e) {
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
isScrolling = undefined;
});
document.getElementById('flipbook').addEventListener('touchmove', function (e) {
const dx = e.touches[0].pageX - startX;
const dy = e.touches[0].pageY - startY;
if (typeof isScrolling === 'undefined') {
isScrolling = Math.abs(dy) > Math.abs(dx);
}
// 防止横向滑动时页面跟随左右滚动
if (!isScrolling) e.preventDefault();
}, { passive: false });
document.getElementById('flipbook').addEventListener('touchend', function (e) {
const dx = e.changedTouches[0].pageX - startX;
if (Math.abs(dx) > 50 && isScrolling === false) {
if (dx > 0) {
goPrev();
} else {
goNext();
}
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment