JS+CSS实现动态翻书效果:3D透视与交互逻辑详解
本文详解如何使用CSS3的3D变换与JavaScript事件监听,实现逼真的动态翻书效果。通过构建左右半本书的DOM结构,利用perspective、transform-origin及rotateY等属性控制页面翻转,并结合鼠标点击与移动事件计算旋转角度,最终完成包含阴影、卡片及整体书体旋转的完整交互案例。
前言
本文将演示一个有趣的交互案例——动态翻书效果。在浏览网页时,我们或许见过类似高校录取通知书的设计,翻开通知书即可展示内部内容,呈现出逼真的3D视觉效果。
首先展示最终实现的效果图:

思路准备
- 将整个书本模型拆分为两个容器:左半本书和右半本书。左半本书包含外表面和内表面,右半本书同样包含内表面和外表面,二者在结构上相当于两个独立的小矩形模块。
- 当鼠标点击并拖拽左半部分时,触发翻开动画。此时仅左半本书绕Y轴进行旋转运动。
- 与此同时,右半书的卡片部分会竖立起来,阴影随之倾斜,整本书也会发生一定角度的旋转,从而增强立体感。
正文
一、CSS实现
1、搭建基本框架
首先定义一个class="book"容器包裹整个书本,内部划分为右半本书和左半本书两个部分,分别使用class="back-cover"和class="front-cover"的div容器表示。右半本书进一步细分为内壳class="page front"和外壳class="page back",左半本书也采用相同的类名结构。在右半书中放置卡片和阴影元素,分别由class="shadow"、class="card"的div容器承载。左半书内壳中放置文字内容,为简化代码,部分盒子添加了公共类名。具体结构如下:
<div class="book p3d">
<!-- 右半本 -->
<div class="back-cover p3d">
<div class="page back flip"></div>
<div class="page front p3d">
<div class="shadow"></div>
<div class="card"></div>
</div>
</div>
<!-- 左半本 -->
<div class="front-cover p3d">
<div class="page front flip p3d">
<p>Solutions to over 1000 popular algorithm problems. All problems are from leetcode.com. Solutions include: - Problem statement - Python code with comments - Description of solution s
trategy - Time and space complexity Does not require internet connection.
Forward solutions by email. Please let me have your comments, correctio…</p>
</div>
<div class="page back"></div>
</div>
</div>2、编写CSS
1)设置背景颜色,实现渐变效果。
body {
height: 100%;
font: 100%/1.25 Arial, Helvetica, sans-serif;//字体类型
color: #fff;
perspective: 1000px; //必不可少!
background: #444;
background-image: linear-gradient(to bottom, #444, #999);
}tips: perspective——定义了观察者与 z=0 平面的距离,使具有三维位置变换的元素产生透视效果,值越大看到的东西越小,不设置看不出translateZ轴移动的近大远小的感觉。perspective-origin——相当于人的眼睛看哪里,默认是父元素中间地方。这两个属性都是设置在父元素身上。
2)设置最外层容器book的样式:宽高设置具体值并使它们在屏幕中间显示——主要利用定位position:absolute实现,top、left的值都为50%,再让它们的左外边距和上外边距为自身宽高的负一半可以实现垂直居中显示。
.book {
width: 300px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -150px;
margin-left: -150px;
}3)设置左半本书和右半本书里面的页面的宽高——和书一样大小,并利用定位——脱离文档流,让这些页面在同一个位置,同时设置内壳背景色为红色,外壳为白色(方便放背景图),让左半本书绕着Y轴旋转。同时设置3D立体效果
.book .page {
width: 300px;
height: 300px;
padding: 1em;
position: absolute;
left: 0;
top: 0;
text-indent: 2em;
}
.book .front {
background-color: #d93e2b;
}
.book .back {
background-color: #fff;
}
.book .front-cover {
cursor: move; //鼠标放上去呈十字架形状
transform-origin: 0 50%;
//transform:rotateY(-160deg) //可以利用这个看看旋转的效果
}
.p3d {
transform-style: preserve-3d;
}4)设置左半本书外层的封面以及右半书的外壳向Z轴平移(解决书的外层布局)
.book .front-cover .back {
background-image: url("https://preview.qiantucdn.com/58pic/35/01/38/55A58PICaUy8sV83Dd78m_PIC2018.jpg%21w1024_new_3072");
background-repeat: no-repeat;
background-size: cover;
transform: translateZ(3px);
}
.book .back-cover .back {
transform: translateZ(-3px);
}5)此时你会发现里面的文字反了,解决办法是让那页反着的页面旋转180度就能正常了。到此为止左半本就完成了!
.book .flip {
transform: rotateY(180deg);
}6)设置右半本书的竖起来的卡片和倒影的位置、大小、颜色,起初两者重叠。
.book .shadow,
.book .card {
width: 196px;
height: 132px;
position: absolute;
top: 60px;
left: 60px;
transform-origin: 0 100%; //设置旋转起点
}
.book .card {
background: url("https://preview.qiantucdn.com/58pic/35/01/38/55A58PICaUy8sV83Dd78m_PIC2018.jpg%21w1024_new_3072");
background-size: cover;
}
.book .shadow {
background-color: rgba(0,0,0,0.5);
}二、JS实现
1)引入js文件到html中
<script src="./index.js"></script>
2)获取到需要的元素。先拿到整本书,再拿到左半本书、卡片、阴影.
let book=document.querySelector('.book'),
leftPage=document.querySelector('.front-cover'),
card=document.querySelector('.card'),
shadow=document.querySelector('.shadow')3)鼠标点击到前半本书移动时开始触发监听事件,可以再window身上设置
window.onmousemove = function(event){}4)用一个变量表示鼠标的状态是点击、移动还是松开,类似于一个开关变量。默认是松开状态。
let hold=false
//鼠标是按住的状态
leftPage.onmousedown=function(){
hold=true
}
window.addEventListener('mouseup',function(){ //鼠标不一定在page身上松开可能在其他地方松开,所以在window身上设置监听事件
hold=false
})5)设置移动事件。监听此时鼠标按下去的那一刻点的X坐标以及移动中的X轴上的变化,从而设置一个合理的值,让它绕Y轴旋转。让书、前半本书、卡片、阴影都能旋转移动角度。
window.onmousemove = function(event){
if(hold){
console.log(event.pageX);
var angle= clamp((window.innerWidth/2 - event.pageX + 300)/300* -90,-180,0) //300为书的宽度
//该angle公式中的值不固定,可以设置其他
// leftPage.style.transform='rotate('+angle+'deg)'
leftPage.style.transform=`rotateY(${angle}deg)`
card.style.transform=`rotateX(${angle/2}deg)`
shadow.style.transform=`skewX(${angle/10}deg)`
book.style.transform=`rotateX(${60+angle/8}deg)`
}
}tips:
- clamp函数中——min:-180deg,max:0deg,中间值:(window.innerWidth/2 - event.pageX + 300)/300* -90。总之这样设置是为了旋转角度比较契合,你也可以设置其他值。该值是在-180~0之间
skewX():指定对象绕X轴斜切扭曲。- 这些旋转的角度都可以设置其他值,不过得设置的比较符合。
6)设置给定3个值中取中间值的函数
let clamp=function(val,min,max) {
return Math.max(min,Math.min(val,max))
}到此为止,动态翻书效果案例结束啦!有没有觉得一种恍然大悟的感觉!说不定以后会用上哟!
完整代码可以点击js/OPENBOOK · nry/first_demo这里下载哟!
总结
到此这篇关于JS+CSS实现超漂亮的动态翻书效果的文章就介绍到这了,更多相关js动态翻书效果内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JavaScript将图片转换为Base64编码的两种途径
2026-11-05 16:43:05
怎么在 Vue 或 React 项目中正确集成 animate.js
2026-11-05 10:23:38
JS注册事件:addEventListener基础语法与参数详解
2026-11-05 08:44:56
JSP和JS的区别:运行环境与服务端/客户端职责解析
2026-11-04 23:34:36
pdf.js 官方下载地址:GitHub Release 获取预编译包
2026-11-04 23:07:27
