好玩的CSS3(5)-- 实现正方体+3D切割轮播图+原生JS

过渡(transition)

  1. 过渡(transition)是CSS3中具有颠覆性的特征之一,我们可以在不使用 Flash 动画或 JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果。
  2. 帧动画:通过一帧一帧的画面按照固定顺序和速度播放。
  3. 语法格式
transition: 要过渡的属性  花费时间  运动曲线  何时开始;
属性 描述
transition 简写属性,用于在一个属性中设置四个过渡属性。
transition-property 规定应用过渡的 CSS 属性的名称。
transition-duration 定义过渡效果花费的时间。默认是 0。
transition-timing-function 规定过渡效果的时间曲线。默认是 “ease”。
transition-delay 规定过渡效果何时开始。默认是 0。

transform转换属性

属性 描述
transform 向元素应用 2D 或 3D 转换。
transform-origin 允许你改变被转换元素的位置。
transform-style 规定被嵌套元素如何在 3D 空间中显示。
perspective 规定 3D 元素的透视效果。
perspective-origin 规定 3D 元素的底部位置。
backface-visibility 定义元素在不面对屏幕时是否可见。

3D变形

3D位移

在CSS3中3D位移主要包括两种函数translateZ()和translate3d()。translate3d()函数使一个元素在三维空间移动。这种变形的特点是,使用三维向量的坐标定义元素在每个方向移动多少。

3D旋转

在三维变形中,我们可以让元素在任何轴旋转。为此,CSS3新增三个旋转函数:rotateX()、rotateY()和rotateZ()
rotate3d(x,y,z,a)
a:是一个角度值,主要用来指定元素在3D空间旋转的角度,如果其值为正值,元素顺时针旋转,反之元素逆时针旋转。

rotateX(a)函数功能等同于rotate3d(1,0,0,a)
3D缩放

通过使用3D缩放函数,可以让元素在Z轴上按比例缩放。默认值为1,当值大于1时,元素放大,反之小于1大于0.01时,元素缩小。当scale3d()中X轴和Y轴同时为1,即scale3d(1,1,sz),其效果等同于scaleZ(sz)。

scaleZ()scale3d()函数单独使用时没有任何效果,需要配合其他的变形函数一起使用才会有效果。

透视(perspective)

perspective 属性定义 3D 元素距视图的距离,以像素计。该属性允许您改变 3D 元素查看 3D 元素的视图。

用法
  1. 当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。
  2. erspective 属性只影响 3D 转换元素。
  3. 它不是真正意义上的3D,只是视觉上的3D
语法
perspective 属性只影响 3D 转换元素。
    <style>
        body{
            perspective: 50px;
            -webkit-perspective: 50px; /* Safari 和 Chrome */
        }
        div{
            width: 200px;
            height: 200px;
            background: red;
            margin: 100px auto;
            transform-origin: center bottom;
        }
        div:hover{
            transform: rotateX(360deg);
            transition: all 2s;
        }
    style>
    
<body>
    <div>div>
body>

transform-style实现正方体

transform–style属性指定嵌套元素是怎样在三维空间中呈现。

语法
transform-style: flat|preserve-3d;

flat:表示所有子元素在2D平面呈现。
preserve-3d:表示所有子元素在3D空间中呈现。

正方体
  1. 将所有的正方形初始化,放在box父元素,定位在同一位置
<style>
        .box{
            width: 200px;
            height: 200px;
            margin: 100px auto;
            position: relative;
            transform-style: preserve-3d;
        }
        .box>div{
            width: 200px;
            height: 200px;
            position: absolute;
            left: 0;
            top: 0;
            text-align: center;
            line-height: 200px;
            color: #fff;
            font-size: 30px;
        }
style>
    <div class="box">
        <div>div>
        <div>div>
        <div>div>
        <div>div>
        <div>div>
        <div>div>
    div>
  1. 正面和背面:比较简单一个向前一个向后根据box移动相同位置
        .box>div:nth-child(1){
            background: rgba(255,44,66,0.1);
            transform: translateZ(-100px);
        }
        .box>div:nth-child(2){
            background: rgba(44,44,66,0.1);
            transform: translateZ(100px);
        }
  1. 左右两个侧面:先移动在进行旋转,如果先旋转,轴也会跟着转动,我们需要考虑轴的变化,在进行移动
        .box>div:nth-child(3){
            background: rgba(255,44,255,0.1);
            transform:  translateX(100px) rotateY(90deg);
            /*transform:  rotateY(90deg) translateZ(100px);*/
        }
        .box>div:nth-child(4){
            background: rgba(255,255,66,0.1);
            transform: translateX(-100px) rotateY(90deg) ;
        }

如果先旋转,等同于以下3D效果

        .box>div:nth-child(3){
                     transform:  rotateY(90deg) translateZ(100px);
                 }
  1. 上面和下面:向上移动和向下移动,不是下面条煮面条吃的那个下面…
       .box>div:nth-child(5){
            background: rgba(20,78,15,0.1);
            transform: translateY(-100px) rotateX(90deg);
        }
        .box>div:nth-child(6){
            background: rgba(75,64,99,0.1);
            transform: translateY(100px) rotateX(90deg);
        }
  1. 给父盒子box加个动画看下效果
        .box{
            animation: rot 6s ease 100ms infinite;
        }
        @keyframes rot {
            0%{
                transform: rotateX(0deg) rotateY(0deg);
            }
            45%{
                transform: rotateX(360deg) rotateY(0deg);
            }
            75%{
                transform: rotateX(360deg) rotateY(360deg);
            }
            100%{
                transform: rotateX(45deg) rotateY(45deg);
            }
        }

简单3D轮播图

  1. html结构,左右按钮,正方体的连续四个正方形(用来存放图片)
<div class="box">
    <ul>
        <li>li>
        <li>li>
        <li>li>
        <li>li>
    ul>
    <ol>
        <li><li>
        <li>>li>
    ol>
div>
  1. 这里我们使用正面和背面,还有上下两个面来实现,先完成基本的CSS
        *{
            margin: 0;
            padding: 0;
        }
        li {
            list-style: none;
        }
        .box{
            width: 590px;
            height: 470px;
            margin: 20px auto;
            position: relative;
        }
        .box ul{
            width: 590px;
            height: 470px;
            position: absolute;
            left: 0;
            top: 0;
            transform-style: preserve-3d;
        }
        .box ul li {
            position: absolute;
            left: 0;
            top: 0;
            width: 590px;
            height: 470px;
        }
        .box ul li:nth-child(1){
            transform: translateZ(235px);
            background: url("https://m.360buyimg.com/babel/jfs/t1/25272/11/13142/102151/5c9d7f42E698a3831/7e3a380c0cfdd6e6.jpg");
        }
        .box ul li:nth-child(2){
            transform: translateZ(-235px) rotateX(180deg);
            background: url("https://img1.360buyimg.com/pop/jfs/t27457/309/2338429905/77954/1f9e82f6/5bffaa95Nf0577fb1.jpg");
        }
        .box ul li:nth-child(3){
            transform:  translateY(235px) rotateX(-90deg);
            background: url("https://m.360buyimg.com/babel/jfs/t1/28360/35/13800/102258/5ca2c318Ef2c75f28/3c8dc2e4267a99c3.jpg");
        }
        .box ul li:nth-child(4){
            transform: translateY(-235px) rotateX(90deg) ;
            background: url("https://m.360buyimg.com/babel/jfs/t1/31969/21/9031/94245/5ca1ffe7Ebb3b5243/4cb7c725fdec9ca4.jpg");
        }
        .box ol{
            position: absolute;
            width: 100%;
            top: 50%;
            margin-top: -25px;
            display: none;
        }
        .box ol li{
            width: 50px;
            height: 50px;
            background: #ccc;
            opacity: .8;
            text-align: center;
            line-height: 50px;
            color: #fff;
            font-size: 30px;
            cursor: pointer;
        }
        .box ol li:first-child{
            float: left;
        }
        .box ol li:last-child{
            float: right;
        }
JS的实现
  1. 获取设置必须的元素
    let box = document.querySelector('.box')
    let ul = document.querySelector('.box ul')
    let ol = document.querySelector('.box ol')
    let leftBtn = document.querySelector('ol li:first-child')
    let rightBtn = document.querySelector('ol li:last-child')
    let i = 0
    let rot = 0
    let timer = null
  1. 开启一个定时器,使用CSS3 transform进行旋转
  2. 每隔一段事件让ul绕着X轴逆时针旋转90deg
    timer = setInterval(function () {
        i = i + 1
        rot = i * 90
        ul.style.transition = 'all 2s linear 0s'
        ul.style.transform = `rotateX(-${rot}deg)`
    },3000)
  1. 当鼠标经过时,显示左右按钮,停止定时器
    box.onmouseenter = function () {
        ol.style.display = 'block'
        clearInterval(timer)
    }
  1. 鼠标离开时开启定时器
    box.onmouseleave = function () {
        timer = setInterval(function () {
            i = i + 1
            rot = i * 90
            ul.style.transition = 'all 2s linear 0s'
            ul.style.transform = `rotateX(-${rot}deg)`
        },3000)
    }
  1. 点击左右边按钮,实现轮播图
    leftBtn.onclick = function () {
        i --
        rot = i * 90
        ul.style.transition = 'all 2s linear 0s'
        ul.style.transform = `rotateX(-${rot}deg)`
    }
    rightBtn.onclick = function () {
        i = i + 1
        rot = i * 90
        ul.style.transition = 'all 2s linear 0s'
        ul.style.transform = `rotateX(-${rot}deg)`
    }
  1. 可能会有一些小bug,还有代码没有封装,看看后面案例即可

3D切割轮播图

需求(效果图,图片地址是京东的地址,可以自己准备)


显然我们的3D切割轮播图和简单的轮播图完全不一样,已经不是原来的配方了;结构也是需要改变,按照原来的结构,是做不出有"递归",我已经试过了…各位也可以试着做以下。那么换种结构思路…

HTML结构
<div class="box">
    <ul>
        <li><span>span><span>span><span>span><span>span>li>
        <li><span>span><span>span><span>span><span>span>li>
        <li><span>span><span>span><span>span><span>span>li>
        <li><span>span><span>span><span>span><span>span>li>
    ul>
    <ol>
        <li><li>
        <li>>li>
    ol>
div>
结构剖析,接下来用我丹青妙手、点屏成蝇的功力画一幅惟妙惟肖、栩栩如生、美轮美奂、出神入化、活灵活现、一挥而就、翩若惊鸿结构图,大家更容易理解

好玩的CSS3(5)-- 实现正方体+3D切割轮播图+原生JS_第1张图片

  1. 四个li浮动放在ul里面每个占据一份排列
  2. 每个li的四个span通过平移选择得到一个围起来的立体图形,如图;因为span是3D效果,其父元素li需要添加preserve-3d.
  3. 第一张背景图片放在每个li的第一个span里面,通过定位拼接(background-position)成一张完整的图片,第二站图片放在每个li的第二个span…
  4. 最后给ul添加preserve-3d,因为我们要通过旋转每个li来实现3D轮播图,切割效果只需要延迟(transition-delay)li的时间
CSS结构:这里进行压缩一下
*{margin:0;padding:0}li{list-style:none}.box{width:590px;height:470px;margin:20px auto;position:relative}.box ul{width:590px;height:470px;transform-style:preserve-3d}.box ul li{width:25%;height:470px;float:left;transform-style:preserve-3d;position:relative}.box ul li span{position:absolute;left:0;right:0;width:100%;height:470px;background-repeat:no-repeat}.box ul li:nth-child(1) span{background-position:left}.box ul li:nth-child(2) span{background-position:33.3333333%}.box ul li:nth-child(3) span{background-position:66.666666%}.box ul li:nth-child(4) span{background-position:right}.box ul li span:nth-child(1){transform:translateZ(235px);background-image:url("https://m.360buyimg.com/babel/jfs/t1/25272/11/13142/102151/5c9d7f42E698a3831/7e3a380c0cfdd6e6.jpg")}.box ul li span:nth-child(2){transform:translateZ(-235px) rotateX(180deg);background-image:url("https://img1.360buyimg.com/pop/jfs/t27457/309/2338429905/77954/1f9e82f6/5bffaa95Nf0577fb1.jpg")}.box ul li span:nth-child(3){transform:translateY(235px) rotateX(-90deg);background-image:url("https://m.360buyimg.com/babel/jfs/t1/24097/4/13958/90976/5ca45d5dEd7dd4aa9/6b5a4d8311d5ef08.jpg")}.box ul li span:nth-child(4){transform:translateY(-235px) rotateX(90deg);background-image:url("https://m.360buyimg.com/babel/jfs/t1/31969/21/9031/94245/5ca1ffe7Ebb3b5243/4cb7c725fdec9ca4.jpg")}.box ol{position:absolute;width:100%;top:50%;margin-top:-25px;display:none}.box ol li{width:50px;height:50px;background:#ccc;opacity:.8;text-align:center;line-height:50px;color:#fff;font-size:30px;cursor:pointer}.box ol li:first-child{float:left}.box ol li:last-child{float:right}
JS实现3D切割轮播图
  1. 获取和设置必须元素
    let box = document.querySelector('.box')
    let ul = document.querySelector('.box ul')
    let ol = document.querySelector('.box ol')
    let leftBtn = document.querySelector('ol li:first-child')
    let rightBtn = document.querySelector('ol li:last-child')
    let ulLi = document.querySelectorAll('ul li')
    let i = 0 //旋转多少次
    let rot = 0 //一次旋转多少度
    let timer = null //定时器
  1. 实现自动轮播
    timer = setInterval(function () {
        i = i + 1
        rot = i * 90
        for(var j = 0;j<ulLi.length;j++){
            // console.log(ulLi[j])
            ulLi[j].style.transform = `rotateX(-${rot}deg)`
            ulLi[j].style.transition = 'all 1s linear 0s'
            ulLi[j].style.transitionDelay = j*200+'ms'
        }
    },3000)
  1. 鼠标经过轮播图时开启定时器,显示左右切换按钮
    box.onmouseenter = function () {
        ol.style.display = 'block'
        clearInterval(timer)
    }
  1. 鼠标离开时,隐藏按钮开启自动轮播
    box.onmouseleave = function () {
        timer = setInterval(function () {
            i = i + 1
            rot = i * 90
            for(var j = 0;j<ulLi.length;j++){
                // console.log(ulLi[j])
                ulLi[j].style.transform = `rotateX(-${rot}deg)`
                ulLi[j].style.transition = 'all 1s linear 0s'
                ulLi[j].style.transitionDelay = j*200+'ms'
            }
        },3000)
        ol.style.display = 'none'
    }
  1. 左右切换按钮实现点击旋转
    leftBtn.onclick = function () {
        i --
        rot = i * 90
        for(var j = 0;j<ulLi.length;j++){
            // console.log(ulLi[j])
            ulLi[j].style.transform = `rotateX(-${rot}deg)`
            ulLi[j].style.transition = 'all 1s linear 0s'
            ulLi[j].style.transitionDelay = j*200+'ms'
        }
    }
    rightBtn.onclick = function () {
        i = i + 1
        rot = i * 90
        for(var j = 0;j<ulLi.length;j++){
            ulLi[j].style.transform = `rotateX(-${rot}deg)`
            ulLi[j].style.transition = 'all 1s linear 0s'
            ulLi[j].style.transitionDelay = j*200+'ms'
        }
    }
  1. 封装并去bug(监听动画效果是否结束,防止多个动画重合)整合版本
    let box = document.querySelector('.box')
    let ul = document.querySelector('.box ul')
    let ol = document.querySelector('.box ol')
    let leftBtn = document.querySelector('ol li:first-child')
    let rightBtn = document.querySelector('ol li:last-child')
    let ulLi = document.querySelectorAll('ul li')
    let i = 0
    let rot = 0
    let timer = null
    let bool = true  //监听动画是否结束
    function liRot(eleAll,eleRot){
        for(var j = 0;j<eleAll.length;j++){
            eleAll[j].style.transform = `rotateX(-${eleRot}deg)`
            eleAll[j].style.transition = 'all 1s linear 0s'
            eleAll[j].style.transitionDelay = j*200+'ms'
        }
    }
    timer = setInterval(function () {
        if(!bool){
            return
        }
        bool = false
        i = i + 1
        rot = i * 90
        liRot(ulLi,rot)
    },3000)
    box.onmouseenter = function () {
        ol.style.display = 'block'
        clearInterval(timer)
    }
    box.onmouseleave = function () {
        timer = setInterval(function () {
            i = i + 1
            rot = i * 90
            liRot(ulLi,rot)
        },3000)
        ol.style.display = 'none'
    }
    leftBtn.onclick = function () {
        if(!bool){
            return
        }
        bool = false
        i --
        rot = i * 90
        liRot(ulLi,rot)
    }
    rightBtn.onclick = function () {
        if(!bool){
            return
        }
        bool = false
        i = i + 1
        rot = i * 90
        liRot(ulLi,rot)
    }
    ulLi[ulLi.length-1].addEventListener('transitionend',function(){
        bool = true
    })

参考文档

CSS3 3D 转换
CSS JS压缩

你可能感兴趣的:(css)