你们给自己写请柬?

效果

需求

鼠标按下能翻开,右边小卡片能弹出,且带有阴影

实现

搭建结构

  • 搭建过程与上一篇时钟类似,这里不过多赘述。
xml 复制代码
<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>
                    亲爱的丁社长和铁锤:

                    恭喜你们迎来人生新的旅程,结婚是爱情的圆满,是幸福的开始。愿你们携手共度人生的每一刻,相互扶持,相互理解,相互包容。

                    在这个特别的日子里,愿你们的爱情如同新婚的阳光一样灿烂,如同甜蜜的蜜蜂一样温暖。愿你们的爱情,如同永恒的星辰,照耀着彼此的人生。

                    愿你们的婚姻充满欢笑与快乐,百年好合,幸福美满!

                    祝福语:
                    丁社长和铁锤,祝你们于2024年5月1日结婚纪念日快乐!

                    祝福你们永结同心,白头偕老!
                </p>
            </div>
            <!-- 外壳 -->
            <div class="page back"></div>
        </div>
    </div>

css

  • background: linear-gradient(to bottom, #444, #999);背景色调成渐变
  • 除了上一篇讲的translate平移的方式,我们还可以通过margin-left: -150px;调整外边距的方式往回走半个身位,确保位置居中
  • cursor: pointer;小手点击图标
  • user-select: none;禁止用户选中
  • transform: rotateX(60deg);饶X轴旋转
  • text-indent: 2em;缩进两个字符
  • transform-origin: 0 50%;调整坐标起始位置
  • transform-style: preserve-3d;设置元素的子元素是位于 3D 空间中还是平面中。
css 复制代码
* {
    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;
    perspective: 1000px;
    background: linear-gradient(to bottom, #444, #999);
}

.book {
    width: 300px;
    height: 300px;
    position: absolute;
    left: 50%;
    margin-left: -150px;
    top: 50%;
    margin-top: -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: #d93e2b;

}

.back {
    background-color: #fff;

}

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

}

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

.front-cover .back {
    background-image: url(https://img2.baidu.com/it/u=2368431681,4265369131&fm=253&fmt=auto&app=138&f=JPEG?w=595&h=500);
    background-size: cover;
    transform: translateZ(3px);
}

.flip {
    transform: rotateY(180deg);
}

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

.pic {
    background: url(https://q4.itc.cn/q_70/images03/20240405/39ec09deda3a41d79e03897b0fdf68a0.jpeg);
    background-size: cover;
}

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

JS

  • document.querySelector类名方式获取元素
  • var hold = false提前设置好标记,后续鼠标点住外壳移动时需要改变状态
  • var clamp = function (val, min, max) { return Math.max(min, Math.min(val, max)) }自己设计一个大概的鼠标拉动时请柬翻转角度
  • 计算好角度后frontCover.style.transform = rotateY(${angle}deg)`js更改css样式
  • 以此类推另外的阴影和pic元素
xml 复制代码
<script>
        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)`
            }

        }
    </script>
相关推荐
开始学java3 分钟前
useEffect 空依赖 + 定时器 = 闭包陷阱?count 永远停在 1 的坑我踩透了
前端
zerosrat3 分钟前
从零实现 React Native(2): 跨平台支持
前端·react native
狗哥哥4 分钟前
🔥 Vue 3 项目深度优化之旅:从 787KB 到极致性能
前端·vue.js
青莲8434 分钟前
RecyclerView 完全指南
android·前端·面试
青莲8435 分钟前
Android WebView 混合开发完整指南
android·前端·面试
GIS之路9 分钟前
GDAL 实现矢量数据转换处理(全)
前端
大厂技术总监下海9 分钟前
Rust的“一发逆转弹”:Dioxus 如何用一套代码横扫 Web、桌面、移动与后端?
前端·rust·开源
加洛斯10 分钟前
SpringSecurity入门篇(2):替换登录页与config配置
前端·后端
用户9047066835711 分钟前
Nuxt详解 —— 设置seo以及元数据
前端
DarkLONGLOVE13 分钟前
Vue组件使用三步走:创建、注册、使用(Vue2/Vue3双版本详解)
前端·javascript·vue.js