这个方案将使用 纯CSS3和少量JavaScript 来实现,无需引入任何外部库(如jQuery),轻量且高效,效果模拟了真实的书籍翻页,包括页面阴影、卷曲效果和3D透视。

html5手机网页电子书翻页效果代码
(图片来源网络,侵删)

最终效果预览


核心实现思路

  1. HTML结构:

    • 一个容器 .book,作为整本书的包裹,设置3D透视。
    • 两个页面 .page,分别代表左页和右页。
    • 每个页面内部包含 .page-front (正面) 和 .page-back (背面),用于实现翻过去后能看到背面内容。
  2. CSS3 (核心部分):

    • 3D变换: 使用 transform-style: preserve-3d; 让子元素可以在3D空间中渲染。
    • 翻页动画: 使用 transform: rotateY(-180deg); 配合 transition 实现平滑的翻页旋转。
    • 页面阴影: 使用 box-shadow 创建逼真的页面厚度和阴影效果。
    • 伪元素: 使用 :before:after 伪元素来创建页面卷曲的边缘和阴影,增加真实感。
  3. JavaScript (交互部分):

    • 监听触摸事件(touchstart, touchmove, touchend)和鼠标事件(mousedown, mousemove, mouseup),以实现移动端和PC端的兼容。
    • 通过计算手指/鼠标的移动距离,动态设置页面的旋转角度,实现“拖拽翻页”的交互。
    • 在翻页结束时,根据最终角度判断是否翻到下一页,并重置状态。

完整代码

你可以直接将以下代码保存为一个 .html 文件,然后在浏览器中打开(建议使用手机浏览器或开启手机模拟模式查看)。

html5手机网页电子书翻页效果代码
(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">HTML5 手机电子书翻页效果</title>
    <style>
        /* 全局样式和重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: 'Microsoft YaHei', sans-serif;
            background: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            overflow: hidden; /* 防止页面滚动 */
            -webkit-user-select: none; /* 禁止文字选择 */
            user-select: none;
        }
        /* 书本容器 */
        .book {
            position: relative;
            width: 90vw; /* 视窗宽度的90% */
            max-width: 400px;
            height: 60vh; /* 视窗高度的60% */
            perspective: 2000px; /* 3D透视距离,值越大,3D效果越弱 */
        }
        /* 单页容器 */
        .page {
            position: absolute;
            width: 50%;
            height: 100%;
            top: 0;
            transform-origin: left center; /* 设置旋转原点在左侧中心 */
            transition: transform 0.5s ease-in-out;
            transform-style: preserve-3d; /* 让子元素在3D空间中呈现 */
            background-color: #fff;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
        }
        /* 右页 */
        .page.right {
            left: 50%;
            border-radius: 0 15px 15px 0;
        }
        /* 左页 */
        .page.left {
            right: 50%;
            border-radius: 15px 0 0 15px;
            transform-origin: right center; /* 左页的旋转原点在右侧 */
        }
        /* 页面的正面和背面 */
        .page-front, .page-back {
            position: absolute;
            width: 100%;
            height: 100%;
            padding: 20px;
            backface-visibility: hidden; /* 背面不可见 */
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
            font-size: 1.2rem;
            color: #333;
        }
        /* 页面背面需要旋转180度,使其内容正向 */
        .page-back {
            transform: rotateY(180deg);
            background-color: #fafafa; /* 背面颜色稍作区分 */
        }
        /* 翻页后的状态 */
        .page.flipped {
            transform: rotateY(-180deg); /* 右页向右翻 */
        }
        .page.left.flipped {
            transform: rotateY(180deg); /* 左页向左翻 */
        }
        /* 页面卷曲和阴影效果 (使用伪元素) */
        .page::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(to right, rgba(0,0,0,0.1) 0%, transparent 10%);
            opacity: 0;
            transition: opacity 0.5s;
            pointer-events: none;
        }
        .page.flipped::before {
            opacity: 1;
        }
        /* 状态提示 */
        .status {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 10px 20px;
            border-radius: 20px;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="status" id="status">点击或拖拽页面进行翻页</div>
    <div class="book" id="book">
        <!-- 左页 -->
        <div class="page left" id="page-left">
            <div class="page-front">
                <h2>第一章:开始</h2>
                <p>欢迎来到这本电子书的世界。</p>
                <p>请点击或拖拽右侧页面开始阅读。</p>
            </div>
            <div class="page-back">
                <!-- 左页的背面通常是上一页的背面,但为了演示,我们留空或放一些装饰 -->
            </div>
        </div>
        <!-- 右页 -->
        <div class="page right" id="page-right">
            <div class="page-front">
                <h2>第一章:开始 (续)</h2>
                <p>HTML5 提供了许多强大的特性,让我们能够创造出更加丰富和互动的网页体验。</p>
                <p>这个翻页效果就是利用 CSS3 的 3D 变换实现的。</p>
            </div>
            <div class="page-back">
                <h2>第二章:探索</h2>
                <p>翻过这一页,我们将探索更多关于 CSS3 的奥秘。</p>
                <p>包括动画、过渡和 3D 变换。</p>
            </div>
        </div>
    </div>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const book = document.getElementById('book');
            const pageLeft = document.getElementById('page-left');
            const pageRight = document.getElementById('page-right');
            const status = document.getElementById('status');
            let isDragging = false;
            let startX = 0;
            let currentPage = 0; // 0: 初始页, 1: 第二页, 2: 第三页
            const totalPages = 3; // 总页数(演示用)
            // 更新状态提示
            function updateStatus(text) {
                status.textContent = text;
            }
            // 翻页逻辑
            function flipPage(pageElement) {
                if (!pageElement.classList.contains('flipped')) {
                    pageElement.classList.add('flipped');
                    currentPage++;
                    updateStatus(`当前页: ${currentPage + 1} / ${totalPages}`);
                } else {
                    pageElement.classList.remove('flipped');
                    currentPage--;
                    updateStatus(`当前页: ${currentPage + 1} / ${totalPages}`);
                }
            }
            // 鼠标/触摸开始
            function handleStart(e) {
                isDragging = true;
                startX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX;
                book.style.cursor = 'grabbing';
            }
            // 鼠标/触摸移动
            function handleMove(e) {
                if (!isDragging) return;
                e.preventDefault(); // 阻止默认行为,如页面滚动
                const currentX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX;
                const diffX = currentX - startX;
                const page = diffX > 0 ? pageLeft : pageRight;
                // 根据拖动距离设置旋转角度
                const rotation = Math.max(-180, Math.min(180, diffX / 2));
                if (page === pageLeft) {
                    pageLeft.style.transform = `rotateY(${rotation}deg)`;
                } else {
                    pageRight.style.transform = `rotateY(${-rotation}deg)`;
                }
            }
            // 鼠标/触摸结束
            function handleEnd(e) {
                if (!isDragging) return;
                isDragging = false;
                book.style.cursor = 'grab';
                const currentX = e.type.includes('mouse') ? e.clientX : e.changedTouches[0].clientX;
                const diffX = currentX - startX;
                // 判断是否翻页(拖动距离超过50px)
                if (Math.abs(diffX) > 50) {
                    if (diffX > 0 && currentPage > 0) {
                        // 向右拖,如果是左页,则翻回
                        pageLeft.style.transform = '';
                        flipPage(pageLeft);
                    } else if (diffX < 0 && currentPage < totalPages - 1) {
                        // 向左拖,如果是右页,则翻过
                        pageRight.style.transform = '';
                        flipPage(pageRight);
                    }
                } else {
                    // 拖动距离不足,回弹
                    pageLeft.style.transform = '';
                    pageRight.style.transform = '';
                }
            }
            // 为书本添加事件监听
            book.addEventListener('mousedown', handleStart);
            book.addEventListener('touchstart', handleStart);
            document.addEventListener('mousemove', handleMove);
            document.addEventListener('touchmove', handleMove);
            document.addEventListener('mouseup', handleEnd);
            document.addEventListener('touchend', handleEnd);
            // 点击翻页
            pageRight.addEventListener('click', () => {
                if (currentPage < totalPages - 1) {
                    flipPage(pageRight);
                }
            });
            pageLeft.addEventListener('click', () => {
                if (currentPage > 0) {
                    flipPage(pageLeft);
                }
            });
            updateStatus(`当前页: ${currentPage + 1} / ${totalPages}`);
        });
    </script>
</body>
</html>

如何扩展和自定义

  1. 增加更多页面:

    • 在HTML中,复制 .page 结构,并根据需要调整 left/right 位置和内容。
    • 在JavaScript中,增加 totalPages 的值。
    • 翻页逻辑需要更复杂一些,通常需要一个数组来管理所有页面的DOM元素,然后根据 currentPage 索引来控制当前显示的页面。
  2. 加载真实内容:

    • 你可以将 .page-front.page-back 中的内容替换为 <div class="content"></div>
    • 通过JavaScript,你可以使用 fetchXMLHttpRequest 从服务器或本地JSON文件加载章节内容,然后动态插入到这些 content div中。
  3. 美化样式:

    • 修改 .pagebackground-colorbox-shadow 来模拟不同质感的纸张。
    • 调整 .bookperspective 值来改变3D效果的强度。
    • .page 内部添加页码、页眉、页脚等元素。
  4. 添加动画效果:

    html5手机网页电子书翻页效果代码
    (图片来源网络,侵删)
    • 目前的代码已经包含了基础的 transition,你可以通过JavaScript动态修改 transition-duration 来实现快慢翻页的效果。
    • 更高级的翻页效果(如撕纸效果、波浪效果)则需要更复杂的CSS和JavaScript,或者使用专门的书本渲染库(如 turn.js)。

这个示例为你提供了一个坚实的基础,你可以在此基础上进行二次开发,打造出功能更完善的手机电子书应用。