如何利用CSS制作简易旋转木马效果

最近回顾动画知识的时候,看到了3d相关的知识,想到了当时学CSS 3动画的时候做的一个旋转木马还挺好看的,今天就来说说怎么用CSS3的变形(transform)和动画(animation)的相关知识做一个简单的3d版的旋转木马效果。

准备工作

首先,想做这个动画,我们要先了解用到的相关属性。

变形

transform:通过这个属性,我们可以对元素进行位移、旋转、缩放、倾斜等操作,其中最常用的就是位移和旋转,缩放和倾斜按需求使用。transform同时支持2d和3d的变形,而本次我们需要的自然就是3d方面的操作了。
说完transform后说说它的子属性:
鉴于本次操作只用到了位移和旋转,所以主要说说这两个属性,其他属性朋友们有兴趣的话可以自己去搜索一下。

  • translate: 通过该属性,可以将元素从当前位置在x,y,z轴位移规定的距离。
    2d复合写法: translate(x,y),表示元素在x轴和y轴位移的距离
    3d复合写法:translate(x,y,z),表示元素在x轴和y轴和z轴位移的距离
    当然,我们也可以单独拆分来写某个轴位移的距离:translateX(),translateY(),translateZ(),就分别表示了在各轴方向上位移的距离。
    注:translate后面的X、Y、Z注意大写,距离可以是负值,表示方向。
  • rotate: 通过该属性,可以将元素从当前位置围绕x,y,z轴旋转规定的角度。这里要注意一下:
    注:2d平面的rotate只有一种写法就是rotate(),而3d上的rotate是有复合写法的
    3d复合写法:
rotate3d() : 四个值 0|1(x轴是否添加旋转角度)  0|1(y轴是否添加旋转角度)  0|1(z轴是否添加旋转角度)  deg

例如:rotate3d(1,1,1,30deg);表示围绕x,y,z各顺时针旋转30度。
而如果我们不想用这种方法,也可以单独拆分来写绕某个轴旋转的角度:rotateX(),rotateY(),rotateZ()

这里同样要注意X、Y、Z的大写,角度可以是负值,表示逆时针旋转。rotateZ()与2d平面中的rotate()效果是相同的。

角度也可以是弧度,但是我们并不常用,而且这里也用不到,所以有兴趣的朋友可以自己搜索一下。
transform-origin: 该元素可以让我们改变元素变形属性的基点,默认位置在元素中心。
transform-style: 定义3d空间,浏览器中的元素默认是在2d平面显示的,我们可以通过改变父元素的transform-style属性值来构造3d的空间.
perspective(景深): 通过景深属性,我们定义距离3d元素多远去观察元素,值越大幅度越小。
perspective-origin:` 该属性可以让我们改变景深的基点,也就是观察3d元素的角度。默认值在元素中心。我们可以通过改变基点在x,y轴的位置来改变观察角度,具体操作待会儿在实践中演示。

动画

animation: 通过该属性我们可以给元素定义动画。animation是以下属性的简写:

  • animation-name: 规定动画名称。
  • animation-duration: 规定动画持续时间。
  • animation-timing-function: 规定动画运动曲线。
  • animation-delay: 规定动画开始前的延迟时间。
  • animation-iteration-count: 规定动画播放次数。
  • animation-direction: 规定动画运动方向。

具体值就不详细介绍了,我第一个博客介绍的挺详细的,或者不懂的朋友也可以上网搜索一下,这里需要注意的就是如果简写属性里写了两个时间,那么第一个是animation-duration的值,第二个是animation-delay的值。

@keyframes规则: 通过该规则规定动画的过程,通过关键词from,to或者百分比设置动画变化的过程。
那么,一切已经准备就绪了,就让我们开始吧:

开始操作

首先,我们可以准备8张图片来做旋转木马的效果,这样我们可以写一个列表,然后给ul构造3d空间即可,为了方便观察,我们在外围在套一个盒子,用于设置景深:

<div id="box">
        <ul class="ff">
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
</div>

就像这样,然后我们就可以将我们喜欢的图片放进去了,我在这里放入了我最喜欢的rpg游戏最终幻想的壁纸:-)
我们给div的宽高设置大一点便于观察,然后因为我这里找的都是1920x1080的图,所以我固定ul的宽高方便图片等比例缩放。

<div id="box">
    <ul class="ff">
        <li><img src="./images/01.jpg" alt="#"></li>
        <li><img src="./images/02.jpg" alt="#"></li>
        <li><img src="./images/03.jpg" alt="#"></li>
        <li><img src="./images/04.jpg" alt="#"></li>
        <li><img src="./images/05.jpg" alt="#"></li>
        <li><img src="./images/06.jpg" alt="#"></li>
        <li><img src="./images/07.jpg" alt="#"></li>
        <li><img src="./images/08.jpg" alt="#"></li>
    </ul>
</div>
body,div,ul,li,img,h2{
    margin: 0;padding: 0;
    list-style: none;
    text-decoration: none;
    font-size: 0;
}
img{
    display: block;
    width: 192px;
}
#box{
    width: 1000px;
    height: 600px;
    margin: 50px auto 0;
    perspective: 1200px;
    perspective-origin:center -500px;
    border: solid red 1px;
}
#box .ff{
    width: 192px;
    height: 108px;
    margin-left: 500px;
    margin-top: 300px;
    transform: translate(-50%,-50%);
    transform-style: preserve-3d;
    border: solid blue 1px;
}
#box .ff li{
    border: solid palevioletred 1px;
}

这里我们给div设置1200像素的景深,并将景深基点改到x轴center,y轴中心往上500px处。并通过相对定位+translate方法给ul在div中居中,并通过preserve-3d将ul构造成3d空间。给他们加个边框便于观察效果。

注:translate()中的百分比是相对于自身宽高百分比进行位移的。

此时效果大概是这样的:
在这里插入图片描述
这里,红色的是div,蓝色的是ul,紫色的是li的边框。因为li是块元素独占一行,所以这里溢出了,但是不用怕,这里我们给li加上绝对定位,让他浮动起来,并给他的父元素加上相对定位,让他相对于ul进行定位。

#box .ff{
    width: 192px;
    height: 108px;
    margin-left: 500px;
    margin-top: 300px;
    transform: translate(-50%,-50%);
    position: relative;
    transform-style: preserve-3d;
    border: solid blue 1px;
}
#box .ff li{
    position: absolute;
    left: 0;
    bottom: 0;
    transform-origin: center center 0;
    z-index: 10;
    border: solid palevioletred 1px;
}

此时效果大概是这样的:
在这里插入图片描述注意,这里我们看到上边有些图片突出的部分,是因为我们给div加了景深,所以我们此时观察的角度是偏上的。
写到这里,接下来该干什么了呢?当然是对li进行旋转和位移了。首先计算一下,八张图,转一周是360度,所以每张图之间间隔的角度应该是360/8=45。
这里我们就可以用结构性为类选择器写:

#box .ff li:nth-of-type(1){
    transform: translateZ(300px);
}
#box .ff li:nth-of-type(2){
    transform: rotateY(-45deg) translateZ(300px);
}
#box .ff li:nth-of-type(3){
    transform: rotateY(-90deg) translateZ(300px);
}
#box .ff li:nth-of-type(4){
    transform: rotateY(-135deg) translateZ(300px);
}
#box .ff li:nth-of-type(5){
    transform: rotateY(-180deg) translateZ(300px);
}
#box .ff li:nth-of-type(6){
    transform: rotateY(-225deg) translateZ(300px);
}
#box .ff li:nth-of-type(7){
    transform: rotateY(-270deg) translateZ(300px);
}
#box .ff li:nth-of-type(8){
    transform: rotateY(-315deg) translateZ(300px);
}
这里要注意了,在transform中,先写rotate和先写translate的效果是不一样的,因为程序执行的时候会先读取后面的属性,就像上面那样,会先读取到translate属性,再读取rotate属性,此时translate属性会受到rotate属性的影响,也就是位移的角度也会发生改变,下面看看效果:

在这里插入图片描述很明显,这正是我们需要的改变 ,但是如果我们先写translate属性的话,此时translate不会受到rotate的影响,这里我们看看会发生什么变化:
在这里插入图片描述我们发现,此时变成了图中这个样子,这是因为位移没有受到旋转的影响,所以只是li本身发生的旋转,位移的轨迹并没有旋转,显然,这并不是我们需要的效果,而在实际情况中,我们也经常会不希望位移受到其他属性的影响,所以到底应该如何写还是要考虑需求。
好的这里说完题外话,我们继续,刚才已经将li变形到了需要的位置,接下来要做的自然就是让它转起来了。

这里可能会有朋友想到,如果我们给每一个li加个动画,让他旋转相应角度不就成功了吗,确实,这样做确实没什么问题,笔者刚开始也是这样做的,但是后来想想,这样其实过于麻烦了些,我们可以注意到,li虽然位置改变了,但还是在ul里面,所以这里我们可以直接给ul定义一个动画,然后让它旋转360度即可,如下:

#box .ff{
            width: 192px;
            height: 108px;
            margin-left: 500px;
            margin-top: 300px;
            transform: translate(-50%,-50%);
            position: relative;
            transform-style: preserve-3d;
            animation: ff 20s infinite linear;
}
@keyframes ff {
    from{
        transform: rotateY(0);
    }
    to{
        transform: rotateY(-360deg)
    }
}

这里我们就可以把边框都去掉了,以免影响美感,然后就会发现我们要的旋转木马效果已经出现了:-)。
当然,你也可以加一些其他的样式,让它变的更好看一些,我就加了些阴影和背景等效果,给大家看一下我的旋转木马…

用css做了个简单的旋转木马效果,图片用的我最喜欢的rpg游戏最终幻想的

发布了7 篇原创文章 · 获赞 1 · 访问量 189

猜你喜欢

转载自blog.csdn.net/weixin_46236141/article/details/104666548