前端三件套实践:翻书动画的创意实现

553 阅读4分钟

前言

你还在为送礼物而纠结烦恼吗?当你不知道该送什么的时候,不妨考虑一下送出这份电子礼物吧!它绝对是一份别出心裁、与众不同的选择哦!

最重要的是这个礼物是充满了创意与惊喜的,也是0成本的。还不快学起来。

效果展示showtime!!!!(需要鼠标点击)

image.png

image.png

image.png

实例分析

html部分

因为书在打开的时候有两个部分,一部分是左半边书,另一部分是右半边书。

书的右半本封面有背面和正面书页,正面书页包含阴影和可能的图片区域;书的左半本封面也有正面书页,其中包含了可编辑的文本,还有背面书页。

结构为

  • book p3d(书)
    • book-cover p3d(右半本书)
      • page back flip(背面)
      • page front p3d(正面)
        • shadow(阴影)
        • pic(图片)
    • front-cover p3d(左半本书)
      • page front flip p3d(正面)
      • page back(背面)
<div class="book p3d">
        <!-- 右半本 -->
        <div class="book-cover p3d">
            <div class="page back flip"></div>
            <div class="page front p3d">
                <div class="shadow"></div>
                <div class="pic"></div>
            </div>
        </div>
        <!-- 左半本 -->
        <div class="front-cover p3d">
            <div class="page front flip p3d">
                <p>
                    内容
                </p>
            </div>
            <!-- 外壳 -->
            <div class="page back"></div>
        </div>
    </div>

css部分

思路分析:

  • 全局样式
    • *选择器去除了所有元素的默认边距、内边框和边框
    • box-sizing: border-box 确保元素的尺寸计算包含边框和内边距
  • 页面布局
    • html和 body 元素的高度设置为 100%,以适应整个页面
    • body的颜色设置为白色,背景有一个从顶部到底部的线性渐变
  • 书的结构
    • book类定义书的整体样式,包括尺寸、位置、旋转和鼠标样式等
  • 书页样式
    • page类定义书页的基本样式,包括宽度、高度、内边距和文本缩进。
  • 书页正反两面
    • front和back分别表示正面和背面的样式
  • 正面封面
    • front-cover类定义正面封面的变换原点和旋转角度
  • 3D效果
    • p3d 类确保 3D 变换样式被保留
    • front-cover.back 为正面封面背面设置背景图像和 Z 轴平移
  • 翻转效果
    • flip类实现文字的翻转效果
  • 阴影和图片
    • shadow和 pic 类定义阴影和图片的位置、尺寸和变换原点
* {
    margin: 0;
    padding: 0;
    border: 0;
    box-sizing: border-box;
}

html {
    height: 100%;
}

body {
    height: 100%;
    font: 100%/1.25 Helvetica, arial, helvetica;
    color: #fff;
    /* 视锥(3d效果) */
    perspective: 1000px;
    /* to bottom从上往下 */
    background: linear-gradient(to bottom, #444, #999);
}

.book {
    width: 300px;
    height: 300px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-top: -150px;
    margin-left: -150px;
    cursor: pointer;
    /* 禁止复制 */
    user-select: none;
    transform: rotateX(60deg);
}

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

.front {
    background-color: pink;
}

.back {
    background-color: #fff;
}

.front-cover {
    transform-origin: 0 50%;
    transform: rotateY(0deg);
}

.p3d {
    transform-style: preserve-3d;
}

.front-cover .back {
    background-image: url(./1.jpg);
    background-size: 90%;
    transform: translateZ(3px);
}

.flip {
    /* 让文字不反 */
    transform: rotateY(180deg);
}

.shadow,
.pic {
    width: 196px;
    height: 132px;
    position: absolute;
    left: 60px;
    top: 60px;
    transform-origin: 0 100%;
}

.shadow {
    background-color: rgb(0, 0, 0, 0.5);
}

.pic {
    background-image: url(./2.jpg);
    background-size: 100%;
}

JavaScript部分

我们要实现按住书移动鼠标继续翻书,松开鼠标停止翻书。并且在翻书的过程中,图片和阴影也在发生变化。所以需要2个监听器。但是两个监听器不能同时监听。那我们要怎么去实现呢?

很简单,我们设置一个布尔类型的变量hold。当我们的鼠标在书上的区域按住了鼠标时,布尔值为true。当鼠标在页面区域松开时,布尔值为false。

我们再设置另外一个监听器监听鼠标移动的距离进而改变书籍旋转角度、阴影倾斜角度和图片的旋转角度。

我们可以这样实现。

首先设置一个clamp函数,限制角度在 -180 到 0 之间。通过计算鼠标在x轴移动的距离计算角度。再设置pic和shadow的transform属性

当hold为true时,书籍旋转角度、阴影倾斜角度和图片的旋转角度随鼠标移动而变化。

var hold = false
var frontCover = document.querySelector('.front-cover')
var shadow = document.querySelector('.shadow')
var pic = document.querySelector('.pic')
var clamp = function (val, min, max) {
    return Math.max(min, Math.min(val, max))
}
//鼠标摁住事件
//摁住为ture
frontCover.onmousedown = function () {
    hold = true
}
//摁住为false
window.onmouseup = function () {
    hold = false
}
//鼠标移动事件
window.onmousemove = function (e) {
    //摁住才能执行
    if (hold == true) {
        var angle = clamp((window.innerWidth / 2 - e.pageX + 300) / 300 * -90, -180, 0)

        frontCover.style.transform = `rotateY(${angle}deg)`
        //pic 要立起来 绕x轴旋转(angle/2)
        pic.style.transform = `rotateX(${angle / 2}deg)`
        //shadow 要沿x轴倾斜(angle/8)
        shadow.style.transform = `skewX(${angle / 8}deg)`
    }

}

结尾

快开始制作独特的电子礼物吧。