利用JavaScript实现简单3D开关书本模型
作者:sAnL1ng散陵
序言
今天我们不聊干货,来看一些用JS也能实现的轻松有趣的小Demo,首先我们先看实验效果图。
看完这张图后 直接把代码附上!
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="style.css" rel="external nofollow" rel="external nofollow" > </head> <body> <div class="book p3d"> <div class="front-cover p3d"> <div class="inside page p3d flip"> <p>瓦罗兰特(VALORANT)是一款第一人称FPS游戏。 与传统FPS游戏不同,游戏中每个角色都拥有其不一样的技能,小队角色之间的技能互相搭配进攻能发挥更强的作用。 背景设定:在近未来的地球世界里,全球范围遭遇了一个重要的事件,名为First Light(原初之光),这个事件改变了地球,带来了生命、科技和政府运行的大转变。 部分地球人在这个事件中获得了超能力,这些拥有超能力的人们被称为“Radiants(辐射人)”,意味着他们是被原初之光辐射从而获得了超能力。</p> </div> <div class="outside page"></div> </div> <div class="back-cover p3d"> <div class="outside page p3d"> <div class="inside page p3d"> <div class="shadow"></div> <div class="card"></div> </div> </div> </div> </div> <script src="index.js"></script> </body> </html>
CSS代码
*{ margin: 0; padding: 0; border: 0; vertical-align: baseline; box-sizing: border-box; /*将容器声明成IE模型*/ } html{ height: 100%; } body{ height: 100%; font: 100% / 1.25 Helvetica,arial,sans-serif; perspective: 1000px; background-color: #444; background-image: linear-gradient(to bottom,#444,#999); } .p3d{ transform-style: preserve-3d; } .book{ width: 300px; height: 300px; position: absolute; left: 50%; top: 50%; /* transform: translateY(-50%); */ margin-top: -150px; color: #fff; -webkit-transform: rotateX(60deg); -moz-transform: rotateX(60deg); -o-transform: rotateX(60deg); user-select: none; } .front-cover{ cursor: move; transform-origin: 0 50%; transform: rotateY(0deg); } .page{ width: 300px; height: 300px; padding: 1em;/*相对父容器大小*/ position: absolute;/*脱离文档流*/ left: 0; top: 0; text-indent: 2em; } .inside{ background-color: #2a0303; } .outside{ background-color: #fff; } .front-cover .outside{ background-image: url(https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.nga.178.com%2Fattachments%2Fmon_202006%2F02%2FjoQ5-38t6XlZ5pT3cS2yo-1o0.png&refer=http%3A%2F%2Fimg.nga.178.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1700461884&t=fb89517f74280d519c31d1b97adb1af3); background-repeat: no-repeat; background-size: cover; transform: translateZ(3px); } .flip{ transform: rotateY(180deg); } .back-cover .outside{ transform: translateZ(-3px); } .back-cover .inside{ background-color: #1e0000; } .card, .shadow{ width: 196px; height: 132px; position: absolute; left: 60px; top: 60px; transform-origin: 0 100%; } .shadow{ background-color: rgba(0,0,0,0.5); } .card{ background-image: url(https://images.9k9k.com/m/gamelib/202011/90947_zkyz.jpg); background-size: cover; transform-origin: 0 100%; }
JS代码
var front = document.getElementsByClassName('front-cover')[0] var book = document.getElementsByClassName('book')[0] var card = document.getElementsByClassName('card')[0] var shadow = document.getElementsByClassName('shadow')[0] var hlod = false var clamp = function(val,min,max){ return Math.max(min,Math.min(val,max)) } //鼠标是否按下 front.onmousedown = function(){ hlod = true } //在window上监听鼠标松开 window.onmouseup = function(){ hlod = false } window.onmousemove = function(e){ if(hlod){ //修改左半边书的角度,卡片旋转,阴影倾斜 var deg = clamp((window.innerWidth / 2 - e.x + 300) / 300 * -90, -180, 0) front.style.transform = `rotateY(${deg}deg)` //整本书立起来 60 + deg / 8 book.style.transform = `rotateX(${60 + deg / 8}deg)` //卡片 deg / 2 card.style.transform = `rotateX(${deg / 3}deg)` //阴影倾斜 deg / 8 (css样式倾斜) shadow.style.transform = `skew(${deg / 8}deg)` } } console.log(front); var front = document.getElementsByClassName('front-cover')[0] var book = document.getElementsByClassName('book')[0] var card = document.getElementsByClassName('card')[0] var shadow = document.getElementsByClassName('shadow')[0] var hlod = false var clamp = function(val,min,max){ return Math.max(min,Math.min(val,max)) } //鼠标是否按下 front.onmousedown = function(){ hlod = true } //在window上监听鼠标松开 window.onmouseup = function(){ hlod = false } window.onmousemove = function(e){ if(hlod){ //修改左半边书的角度,卡片旋转,阴影倾斜 var deg = clamp((window.innerWidth / 2 - e.x + 300) / 300 * -90, -180, 0) front.style.transform = `rotateY(${deg}deg)` //整本书立起来 60 + deg / 8 book.style.transform = `rotateX(${60 + deg / 8}deg)` //卡片 deg / 2 card.style.transform = `rotateX(${deg / 3}deg)` //阴影倾斜 deg / 8 (css样式倾斜) shadow.style.transform = `skew(${deg / 8}deg)` } } console.log(front);
代码解释
html部分
引入文件
我们创建的CSS和js文件都需要引入到html文件中
在头部标记里用link方法引入css文件
<head> <link rel="stylesheet" href="style.css" rel="external nofollow" rel="external nofollow" > </head>
在body里用< script >标签引入js文件
<body> <script src="index.js"></script> </body>
HTML框架构建(BEM命名法)
我们将整本书分成了多个部分,总体就是一个book,然后根据想要实现的效果或者其功能将其划分成不同子块
<div class="book p3d"> <div class="front-cover p3d"> <div class="inside page p3d flip"> <p> </div> <div class="outside page"></div> </div> <div class="back-cover p3d"> <div class="outside page p3d"> <div class="inside page p3d"> <div class="shadow"></div> <div class="card"></div> </div> </div> </div> </div>
结构划分完了剩下的交给CSS样式编写就可以了。
CSS样式编写
*{ margin: 0; padding: 0; border: 0; vertical-align: baseline; box-sizing: border-box; /*将容器声明成IE模型*/ }
浏览器默认会给body加一个内外边距,所以我们将其设置为0,之前文章我们了解知道了,CSS中有两种盒模型,我们现在将其设置为box-sizing:border-box IE盒模型,为了让页面效果更完美的展现出来。
-webkit-transform: rotateX(60deg); -moz-transform: rotateX(60deg); -o-transform: rotateX(60deg);
-webkit-transform、-moz-transform、-o-transform分别是针对不同浏览器的前缀,以兼容不同浏览器。在现代浏览器中,大多数已经支持transform属性并可以省略前缀。
这里我们是将元素绕X轴旋转60度,但需要注意编写的时候具体怎么设置角度,我们需要还要根据页面呈现效果和其他样式属性来确定。
.page{ width: 300px; height: 300px; padding: 1em; position: absolute; left: 0; top: 0; text-indent: 2em; }
padding: 1em;
em是指相对父容器大小
position: absolute;
会导致其脱离文档流
JS交互功能编写
在这段JS代码中,主要是用来实现当我们通过鼠标拖拽前封面(front)时,会触发相应的事件,从而控制页面元素的旋转角度,实现一个交互效果。
var front = document.getElementsByClassName('front-cover')[0] var book = document.getElementsByClassName('book')[0] var card = document.getElementsByClassName('card')[0] var shadow = document.getElementsByClassName('shadow')[0]
具体来说,首先通过document.getElementsByClassName()方法获取了front、book、card、shadow四个元素。
front.onmousedown = function(){ hlod = true }
并定义了hlod变量表示鼠标是否按下。
front.onmousedown = function(){ hlod = true } window.onmouseup = function(){ hlod = false }
接下来,代码通过给front元素绑定mousedown事件来监听鼠标按下的动作,当鼠标按下时,将hlod设为true。然后,通过给window绑定mousemove和mouseup事件来监听鼠标移动和松开的动作。当鼠标移动时,如果hlod为true,就计算出deg的值,其值由用户当前鼠标位置决定。clamp()函数用于限制deg变量的取值范围在-180到0之间。随后,代码通过修改相应元素的transform属性来实现立体旋转的效果:front元素绕Y轴旋转deg度,book元素绕X轴旋转60 + deg / 8度,card元素绕X轴旋转deg / 3度,shadow元素skew倾斜deg / 8度。其中,模板字面量语法被用来构建包含变量的字符串,方便设置transform的属性值。
最后,console.log()函数用于输出front元素的信息用于检查调整。
以上就是利用JavaScript实现简单3D开关书本模型的详细内容,更多关于JavaScript 3D开关书本的资料请关注脚本之家其它相关文章!