热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CSS动画之旋转魔方轮播

为什么80%的码农都做不了架构师?下面我将一步一步详解如何利用纯CSS实现一个旋转魔方轮播的效果。总的来说我们需要实现以下两个主要功能:构建一个能

为什么80%的码农都做不了架构师?>>>   hot3.png

下面我将一步一步详解如何利用纯CSS实现一个旋转魔方轮播的效果。

总的来说我们需要实现以下两个主要功能:

  • 构建一个能够旋转的立方体

  • 让立方体拥有基本轮播所具有的特性

但在完成以上两点之前我们需要再次了解或熟悉一下实现其功能的CSS3基础知识点:

  1. transition

  2. transform

  3. perspective

  4. preserve-3d

  5. animation

transition属性 --- 过渡效果

transition: property duration timing-fucntion delay;

这个属性应该都很熟悉, 也不过多讲, 只是列出其所具有的所有子属性。

过渡属性 --- 过渡持续时间 --- 过渡函数(曲线) --- 过渡延迟

transition-timing-function: linear|ease|ease-in|ease-out|ease-in-out; 原生具有的基本过渡函数

transform属性 --- 对元素进行2D或3D转换

它有几个常用的变换方法:scale scale3d translate translate3d rotate rotate3d 等。

transform-origin: x-axis y-axis z-axis; 设置旋转元素的基点位置transform-style: preserve-3d; 让转换的子元素保留3D转换(与perspective搭配使用)

perspective属性 --- 让元素实现3D透视效果

perspective: 1000px;它有两种写法
transform: perspective(1000px);

这个属性让物体具有立体的3D透视效果, 值越大物体离此时我们的眼睛看到屏幕里物体的距离就越远, 相反若它的值越小, 离我们的视角就越近, 即在屏幕中显示的大小就越大。它和preserve-3d共同使用在需要实现3D效果的父元素上搭建舞台视角, 让其子元素能够实现真正的3D转换。

一个基本的立方体就需要结合以上三点属性来实现。

Cube


重要的CSS样式

.cube-wrap{width: 300px;height: 300px;perspective: 1000px;position: relative;
}
.cube-wrap .cube{width: 100%;height: 100%;position: absolute;transform-style: preserve-3d;transition: all .5s ease;
}
.cube-wrap .cube .cube-face{width: 100%;height: 100%;position: absolute;overflow: hidden;opacity: 0.9;border: 1px solid #ccc;
}
.cube-wrap .cube .cube-face img{width: 100%;height: 100%;
}
.cube-face.front{transform: translateZ(150px);
}
.cube-face.back{transform: rotateX(180deg) translateZ(150px);
}
.cube-face.left{transform: rotateY(-90deg) translateZ(150px);
}
.cube-face.right{transform: rotateY(90deg) translateZ(150px);
}
.cube-face.top{transform: rotateX(90deg) translateZ(150px);
}
.cube-face.bottom{transform: rotateX(-90deg) translateZ(150px);
}

在这里我们给父元素使用了perspective和preserve-3d, 接下来子元素的3D变换效果才会生效。

那么重点来了, 上面的代码是如何拼接为一个完整的立方体的呢?在浏览器开发者工具里面仔细观察一下不难发现, 类名为cube元素所在位置是在立方体正中间的那一面。因此我们在如何利用代码构造立方体的每一面时就有了思路。

首先要清楚, transform相关变换时建立的空间直角坐标系x, y , z轴的方向。

即以电脑屏幕为平面, 水平方向为x轴, 竖直方向为y轴, 垂直于屏幕方向的为z轴。

所以如何构建立方体的六个面就变得很简单了, cube 面的初始位置在正中间, 整个立方体的长度为 300px, 因此 translateZ(150px) 即为正面。要想构造背面, 则先需要逆时针反转初始面 180deg , 这时候的正面指向背面, 所以只需再 translateZ(150px) 即可。要构造左面则需绕y轴旋转rotateY(-90deg) , 相应的右侧则为rotateY(90deg) ,然后再进行translateZ(150px) 的平移,剩下的两个面同理按照相应的逻辑进行即可。 需要注意的是当一个面绕轴转动时, 逆时针转动为正值, 顺时针为负值。

animation属性

这个属性在CSS3动画中肯定是最重要的了, 它的每一个子属性都值得我们去仔细研究。

animation: name duration timing-function delay iteration-count direction fill-mode play-state;animation-delay: 1s; 设置为负值时让动画马上开始, 并且跳过1秒前的动画animation-direction: normal|reverse|alternate|alternate-reverse; 定义是否循环交替反向播放动画alternate 动画在奇数次(1、3、5...)正向播放, 在偶数次(2、4、6...)反向播放
alternate-reverse 动画在奇数次(1、3、5...)反向播放, 在偶数次(2、4、6...)正向播放animation-fill-mode: none|forwards|backwards|both; 规定当动画不播放时, 要应用到元素的样式forwards 动画结束后停留在最后一帧
backwards 在animation-delay期间启动动画的第一帧属性
both 同时实现forwards与backwards的效果animation-play-state: paused|running; 控制动画暂停或运行。@keyframes 设置动画关键帧, 在这里我们用from...to或者百分比来实现自定义的动画

animation详解

下面我们给已经构建好的立方体添加上animation动画:

.cube-wrap .cube{......animation: spin 10s linear infinite;
}
@keyframes spin {from {transform: rotateX(45deg) rotateY(45deg);}to {transform: rotateX(405deg) rotateY(765deg);}
}

Carousel

现在我们已经实现了能够自由旋转的立方体效果了, 接下来就需要完成轮播所具有的基本功能。

  1. 左右按钮切换

  2. 底部按钮切换

在实现这两个功能之前我们需要了解一下两个强大的HTML标签, 它们的配合使用实现了轮播图中点击切换的效果。它们就是label和input标签, 先来看看它们的基本用法。

点击label标签, id为1的input标签被选中

这里label标签中的for与input标签中的id相关联, 而input标签中type为radio时是选择框的效果, 它具有一个checked的属性 (若要实现单选框的效果, 则需要设置name="xxx" ,此时的名称要一致, 下文就用到了这个效果)

现在就来开始实现具体的效果吧。

......

先实现左右和底部的CSS样式

.cube_left .cube_action{left: -75px;top: 50%;transform: translateY(-50%);
}
.cube_right .cube_action{right: -75px;top: 50%;transform: translateY(-50%);
}
.cube_action{background-color: #fafafa;border-radius: 50%;cursor: pointer;display: none;width: 40px;height: 40px;opacity: 0.15;position: absolute;transition: opacity 0.5s ease;z-index: 5;
}
.cube_action:hover{opacity: 1;
}
.cube_action::before{border-bottom: 4px solid #111;border-right: 4px solid #111;content: '';display: block;height: 25%;left: 50%;position: absolute;top: 50%;width: 25%;transform: translate(-70%, -50%) rotate(-45deg);
}
.cube_left .cube_action::before{transform: translate(-40%, -50%) rotate(135deg);
}
.indicators{position: absolute;left: 0;right: 0;bottom: -80px;padding: 20px;text-align: center;opacity:0;transition: opacity .3s;
}
.container:hover .indicators{opacity: 1;
}
.indicators .indicator{background-color: #fafafa;border-radius: 50%;cursor: pointer;display: inline-block;width: 14px;height: 14px;margin: 6px;opacity: .15;
}
.controller{display: none;
}

写完上面的代码后并不能看到我们想要的结果, 因为它们都需要hover事件来触发。

现在我们来设置最外层 container 的样式以及定义一个入场动画。

.container{width: 600px;height: 600px;position: absolute;top: 50%;left: 50%;margin-top: -300px;margin-left: -300px;transition: all .5s ease;transform: scale(0.25);
}
.container:hover {transform: scale(1);
}
.container:hover .cube-wrap .cube{animation: entrance .5s ease ;
}
@keyframes entrance {from {transform: rotateX(-225deg) rotateY(-225deg);}
}

当鼠标移入立方体时, 动画由spin被替换为entrance 。

那么重点再次出现了, 到底CSS是如何实现点击切换轮播图片的呢?

原理很简单, 其实就是搭配前面提到的label标签和input标签从而实现了惊人的效果。

.controller:nth-of-type(1):checked ~ .cube{transform: translateZ(-150px);
}
.controller:nth-of-type(2):checked ~ .cube{transform: translateZ(-150px) rotateX(-180deg) ;
}
.controller:nth-of-type(3):checked ~ .cube{transform: translateZ(-150px) rotateY(90deg) ;
}
.controller:nth-of-type(4):checked ~ .cube{transform: translateZ(-150px) rotateY(-90deg) ;
}
.controller:nth-of-type(5):checked ~ .cube{transform: translateZ(-150px) rotateX(-90deg) ;
}
.controller:nth-of-type(6):checked ~ .cube{transform: translateZ(-150px) rotateX(90deg) ;
}

无论是点击左右的按钮, 还是点击底部的按钮, 我们都触发了label标签的for属性从而联动了对应的input标签中的checked属性。

至于该如何将对应的那一面反转到正对屏幕的这一面, 只需要在构造立方体每一面的转换中将符号反向即可。

值得注意的是这里我们运用的CSS选择器也算是一个技巧, :nth-of-type(n) 选择的是相同类型标签的第n个标签, ~符号选择的是同级中的标签。

现在我们回过头来再仔细看下开头的HTML结构, indicators 里面的label标签中的for好像能够明白其逻辑, 即点击哪一个标签就触发哪一个input标签的checked属性从而进行相应的3D转换。 可是左右按钮中的label标签里的for数字顺序咋看起来不对劲呢?

在这里我自己也琢磨了很久, 费了很大的功夫才想明白原来.cube_left或者.cube_right 中相应的6个label标签是重合在一起的, 而且都为display:none , 这就很有意思了, 来看看接下来的代码。

.container:hover .controller:nth-of-type(1):checked ~ .cube_left .cube_action:nth-of-type(1),
.container:hover .controller:nth-of-type(1):checked ~ .cube_right .cube_action:nth-of-type(1){display: block;
}
.container:hover .controller:nth-of-type(2):checked ~ .cube_left .cube_action:nth-of-type(2),
.container:hover .controller:nth-of-type(2):checked ~ .cube_right .cube_action:nth-of-type(2){display: block;
}
......
......
......
.container:hover .controller:nth-of-type(6):checked ~ .cube_left .cube_action:nth-of-type(6),
.container:hover .controller:nth-of-type(6):checked ~ .cube_right .cube_action:nth-of-type(6){display: block;
}

现在我们默认的是 controller 中的第一个元素被选中, 即它的checked属性为true。因此左右按钮里label标签中的第一个显示为display:block , 若现在点击左边的按钮, 我们希望立方体的底部呈现在屏幕的正面, 所以for应该设置为6。若点击右边按钮其第一个label标签的for应该设置为2。按照这个逻辑, 我们也就明白了为什么.cube_left.cube_right中的for属性是乱序的原因了。

结语

感谢您的观看,如有不足之处,欢迎批评指正。

这里推荐一下我的前端学习交流圈:784783012 ,里面都是学习前端的从最基础的HTML+CSS+JS【炫酷特效,游戏,插件封装,设计模式】到移动端HTML5的项目实战的学习资料都有整理,送给每一位前端小伙伴。最新技术,与企业需求同步。好友都在里面学习交流,每天都会有大牛定时讲解前端技术!

点击:加入


转:https://my.oschina.net/zybc/blog/3037260



推荐阅读
  • [c++基础]STL
    cppfig15_10.cppincludeincludeusingnamespacestd;templatevoidprintVector(constvector&integer ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 本项目通过Python编程实现了一个简单的汇率转换器v1.02。主要内容包括:1. Python的基本语法元素:(1)缩进:用于表示代码的层次结构,是Python中定义程序框架的唯一方式;(2)注释:提供开发者说明信息,不参与实际运行,通常每个代码块添加一个注释;(3)常量和变量:用于存储和操作数据,是程序执行过程中的重要组成部分。此外,项目还涉及了函数定义、用户输入处理和异常捕获等高级特性,以确保程序的健壮性和易用性。 ... [详细]
  • 本文详细探讨了使用纯JavaScript开发经典贪吃蛇游戏的技术细节和实现方法。通过具体的代码示例,深入解析了游戏逻辑、动画效果及用户交互的实现过程,为开发者提供了宝贵的参考和实践经验。 ... [详细]
  • 思科IOS XE与ISE集成实现TACACS认证配置
    本文详细介绍了如何在思科IOS XE设备上配置TACACS认证,并通过ISE(Identity Services Engine)进行用户管理和授权。配置包括网络拓扑、设备设置和ISE端的具体步骤。 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 利用REM实现移动端布局的高效适配技巧
    在移动设备上实现高效布局适配时,使用rem单位已成为一种流行且有效的技术。本文将分享过去一年中使用rem进行布局适配的经验和心得。rem作为一种相对单位,能够根据根元素的字体大小动态调整,从而确保不同屏幕尺寸下的布局一致性。通过合理设置根元素的字体大小,开发者可以轻松实现响应式设计,提高用户体验。此外,文章还将探讨一些常见的问题和解决方案,帮助开发者更好地掌握这一技术。 ... [详细]
  • 在使用Eclipse进行调试时,如果遇到未解析的断点(unresolved breakpoint)并显示“未加载符号表,请使用‘file’命令加载目标文件以进行调试”的错误提示,这通常是因为调试器未能正确加载符号表。解决此问题的方法是通过GDB的`file`命令手动加载目标文件,以便调试器能够识别和解析断点。具体操作为在GDB命令行中输入 `(gdb) file `。这一步骤确保了调试环境能够正确访问和解析程序中的符号信息,从而实现有效的调试。 ... [详细]
  • 在 LeetCode 的“有效回文串 II”问题中,给定一个非空字符串 `s`,允许删除最多一个字符。本篇深入解析了如何判断删除一个字符后,字符串是否能成为回文串,并提出了高效的优化算法。通过详细的分析和代码实现,本文提供了多种解决方案,帮助读者更好地理解和应用这一算法。 ... [详细]
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • 在Django中提交表单时遇到值错误问题如何解决?
    在Django项目中,当用户提交包含多个选择目标的表单时,可能会遇到值错误问题。本文将探讨如何通过优化表单处理逻辑和验证机制来有效解决这一问题,确保表单数据的准确性和完整性。 ... [详细]
  • 深入解析 Android 中 EditText 的 getLayoutParams 方法及其代码应用实例 ... [详细]
  • 针对图像分类任务的训练方案进行了优化设计。通过引入PyTorch等深度学习框架,利用其丰富的工具包和模块,如 `torch.nn` 和 `torch.nn.functional`,提升了模型的训练效率和分类准确性。优化方案包括数据预处理、模型架构选择和损失函数的设计等方面,旨在提高图像分类任务的整体性能。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
author-avatar
枪手杰_863
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有