【附有代码】🔥🔥🔥用JS实现一个简单的3D开关书本模型🔥🔥🔥

序言

今天我们不聊干货,来看一些用JS也能实现的轻松有趣的小Demo,首先我们先看实验效果图。

看完这张图后 直接把代码附上!

HTML代码

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">
</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代码

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代码

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文件

html 复制代码
<head>
<link rel="stylesheet" href="style.css">
</head>

在body里用< script >标签引入js文件

html 复制代码
<body>
<script src="index.js"></script>
</body>

HTML框架构建(BEM命名法)

我们将整本书分成了多个部分,总体就是一个book,然后根据想要实现的效果或者其功能将其划分成不同子块

js 复制代码
<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样式编写

js 复制代码
*{
    margin: 0;
    padding: 0;
    border: 0;
    vertical-align: baseline;
    box-sizing: border-box;  /*将容器声明成IE模型*/
}

浏览器默认会给body加一个内外边距,所以我们将其设置为0,之前文章我们了解知道了,CSS中有两种盒模型,我们现在将其设置为box-sizing:border-box IE盒模型,为了让页面效果更完美的展现出来。

js 复制代码
-webkit-transform: rotateX(60deg);
    -moz-transform: rotateX(60deg);
    -o-transform: rotateX(60deg);

-webkit-transform、-moz-transform、-o-transform分别是针对不同浏览器的前缀,以兼容不同浏览器。在现代浏览器中,大多数已经支持transform属性并可以省略前缀。

这里我们是将元素绕X轴旋转60度,但需要注意编写的时候具体怎么设置角度,我们需要还要根据页面呈现效果和其他样式属性来确定。

js 复制代码
.page{
    width: 300px;
    height: 300px;
    padding: 1em;
    position: absolute;
    left: 0;
    top: 0;
    text-indent: 2em;
}

padding: 1em; em是指相对父容器大小

position: absolute;会导致其脱离文档流

JS交互功能编写

在这段JS代码中,主要是用来实现当我们通过鼠标拖拽前封面(front)时,会触发相应的事件,从而控制页面元素的旋转角度,实现一个交互效果。

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]

具体来说,首先通过document.getElementsByClassName()方法获取了front、book、card、shadow四个元素。

js 复制代码
front.onmousedown = function(){
    hlod = true
}

并定义了hlod变量表示鼠标是否按下。

js 复制代码
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元素的信息用于检查调整。

感谢大家的阅读,点点赞吧♥

如果想了解更多有用的干货,点赞+收藏第一时间获取有用的小知识

开源Git仓库: gitee.com/cheng-bingw...

更多内容:【JS前端面试】轻松理解掌握 JS 中 调用栈 作用域链 闭包相关考点

相关推荐
我是苏苏21 分钟前
C# Main函数中调用异步方法
前端·javascript·c#
转角羊儿32 分钟前
uni-app文章列表制作⑧
前端·javascript·uni-app
hong_zc1 小时前
初始 html
前端·html
赛丽曼1 小时前
Python中的HTML
python·html
前端Hardy1 小时前
探索 HTML 和 CSS 实现的 3D 开关按钮
css·3d·html
小小吱1 小时前
HTML动画
前端·html
Bio Coder1 小时前
学习用 Javascript、HTML、CSS 以及 Node.js 开发一个 uTools 插件,学习计划及其周期
javascript·学习·html·开发·utools
钢铁小狗侠2 小时前
前端(1)——快速入门HTML
前端·html
凹凸曼打不赢小怪兽2 小时前
react 受控组件和非受控组件
前端·javascript·react.js
忠实米线3 小时前
使用pdf-lib.js实现pdf添加自定义水印功能
前端·javascript·pdf