vue实现书本翻页效果
实现思路
使用CSS 3D变换和过渡效果模拟书本翻页的立体感,结合Vue的数据绑定和事件处理实现交互控制。核心在于将翻页动作分解为多个阶段,通过JavaScript动态调整CSS属性。
基础HTML结构
<template>
<div class="book-container">
<div class="book">
<div
class="page"
v-for="(page, index) in pages"
:key="index"
:class="{ 'active': currentPage === index }"
>
{{ page.content }}
</div>
</div>
<button @click="flipPage(-1)">上一页</button>
<button @click="flipPage(1)">下一页</button>
</div>
</template>
CSS关键样式
.book-container {
perspective: 1500px;
margin: 50px auto;
}
.book {
position: relative;
width: 300px;
height: 400px;
transform-style: preserve-3d;
}
.page {
position: absolute;
width: 100%;
height: 100%;
background: white;
border: 1px solid #ccc;
box-shadow: 0 0 5px rgba(0,0,0,0.1);
transform-origin: left center;
transition: transform 1s ease;
backface-visibility: hidden;
}
.page.active {
transform: rotateY(0deg);
}
.page.flipping {
transform: rotateY(-180deg);
z-index: 10;
}
Vue组件逻辑
<script>
export default {
data() {
return {
currentPage: 0,
pages: [
{ content: '第一页内容' },
{ content: '第二页内容' },
{ content: '第三页内容' }
],
isFlipping: false
}
},
methods: {
flipPage(direction) {
if (this.isFlipping) return;
const newPage = this.currentPage + direction;
if (newPage < 0 || newPage >= this.pages.length) return;
this.isFlipping = true;
const currentPageEl = document.querySelectorAll('.page')[this.currentPage];
currentPageEl.classList.add('flipping');
setTimeout(() => {
currentPageEl.classList.remove('flipping');
this.currentPage = newPage;
this.isFlipping = false;
}, 1000);
}
}
}
</script>
高级优化方案
添加阴影效果增强立体感
.page.flipping {
box-shadow:
-10px 0 20px rgba(0,0,0,0.2),
inset -10px 0 10px rgba(0,0,0,0.1);
}
实现连续翻页动画
async flipMultiplePages(targetPage) {
const steps = Math.abs(targetPage - this.currentPage);
const direction = targetPage > this.currentPage ? 1 : -1;
for (let i = 0; i < steps; i++) {
await this.flipPageAsync(direction);
}
}
flipPageAsync(direction) {
return new Promise(resolve => {
this.flipPage(direction);
setTimeout(resolve, 1000);
});
}
移动端适配
添加触摸事件支持
<div
class="page"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
></div>
touchStart(e) {
this.startX = e.touches[0].clientX;
},
touchMove(e) {
const moveX = e.touches[0].clientX;
const diff = this.startX - moveX;
if (Math.abs(diff) > 50) {
this.flipPage(diff > 0 ? 1 : -1);
}
}






