纯CSS3制作卡通场景汽车动画效果

前言
今天分享一下我昨晚做的CSS3动画效果——卡通场景汽车动画。在接触CSS3动画之前,我之前实现一些简单的动画效果都是使用flash完成的。但是自从CSS3横空出世,在移动端对CSS3动画的运用越来越多。今天这个分享是PC端的案例,因为我做的是大场景来的,起因还是我无意间看到一张卡通图片。于是我突发灵感,就趁热打铁使用CSS3动画把它按照自己的想法实现了出来。接下来,就让我们一起进入这个好玩的分享吧!

预览
学习一个案例要有热情,就应该先看一下案例的效果,所以,下图为我录的gif图片,大家先看一下:


没错,上图中每一个细节都是使用CSS3制作的,有没有感觉像flash做的,哈哈!!!
此图还是有掉帧或者卡顿现象,我这里提供在线查看地址:
http://www.jr93.top/cartoonAnimation/index.html
我已经对所有主流浏览器都做了兼容,但是有时候动画太快会有模糊现象,这个我暂定认为是浏览器渲染问题。

正题
OK,接下来我将仔细分析一下这个案例的每一部分效果,但是可以看到其实场景有很多重复的小部分,比如窗户,树,山等。那么我就将选取其中一个作为此次讲解的对象。另外,这个案例的工作量还是偏多的,所以我不会每一个步骤都讲得很到位,主要还是把我的思路讲解一下,给大家自己思考吸取。文章最后我会把github地址告诉大家,方便使用这里案例。接下来就赶紧进入主题吧!
首先,肯定是搭建html结构,这个的话需要根据自己对场景的剖析,做到自己心里有数,然后就会很自然地将html结构搭建出来。本案例html代码如下:

<div class="container">
    <!-- 山 -->
    <div class="mountain">
        <div class="part_one"></div>
        <div class="part_two"></div>
        <div class="part_three"></div>
        <div class="part_four"></div>
    </div>
    <!-- 道路 -->
    <div class="load"></div>
    <!-- 石头 -->
    <div class="stone"></div>
    <!-- 太阳 -->
    <div class="sun">
        <div class="sunshine"></div>
        <div class="center_sun"></div>
    </div>
    <!-- 云朵 -->
    <div class="cloud"></div>
    <!-- 房子 -->
    <div class="house">
        <!-- 旗子部分 -->
        <div class="flag_whole">
            <!-- 旗杆 -->
            <div class="pole"></div>
            <!-- 旗面 -->
            <div class="flag">
                <span class="star"></span>
                <span class="littlestar star1"></span>
                <span class="littlestar star2"></span>
                <span class="littlestar star3"></span>
                <span class="littlestar star4"></span>
            </div>
        </div>
        <!-- 墙面 -->
        <div class="wall"></div>
        <!-- 房顶 -->
        <div class="roof"></div>
        <!-- 二楼 -->
        <div class="secondFloor">
            <!-- 窗户 -->
            <div class="window w1">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
            <div class="window w2">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
            <div class="window w3">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
            <div class="window w4">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
        </div>
        <div class="firstFloor">
            <!-- 窗户 -->
            <div class="window f-w1">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
            <div class="window f-w2">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
            <!-- 门 -->
            <div class="door">
                <!-- 门梁 -->
                <div class="door_over"></div>
                <!-- 门主体 -->
                <div class="door_body">
                    <div class="leftDoor"></div>
                    <div class="rightDoor"></div>
                </div>
            </div>
            <div class="window f-w3">
                <!-- 窗户帐篷 -->
                <div class="window_tent"></div>
                <!-- 窗体 -->
                <div class="window_body"></div>
            </div>
        </div>
    </div>
    <!-- 树 -->
    <div class="trees">
        <div class="leftTree"><span></span></div>
        <div class="leftTree l2"><span></span></div>
        <div class="rightTree"><span></span></div>
        <div class="rightTree r2"><span></span></div>
    </div>
    <!-- 第一辆汽车 -->
    <div class="car">
        <div class="car_body">
            <div class="car_top1"></div>
            <div class="car_top2"></div>
            <div class="car_win1"></div>
            <div class="car_win2"></div>
            <div class="car_bottom1"></div>
            <div class="car_bottom2"></div>
        </div>
        <div class="frontWheel"></div>
        <div class="endWheel"></div>
        <div class="exhaust"></div>
    </div>
    <!-- 第二辆车(浅绿色) -->
    <div class="car2">
        <div class="car2_top"></div>
        <div class="car2_win"></div>
        <div class="car2_bottom">
            <div class="car2_light1"></div>
            <div class="car2_light2"></div>
            <div class="car2_light3"></div>
        </div>
        <div class="car2_frontWheel"></div>
        <div class="car2_endWheel"></div>
    </div>
</div>

是不是够多的,我都预感博文篇幅会很长,大家要保持耐心哦!还是需要仔细看一下html结构,因为接下来就都是CSS3干的活了:
这里先对最外层的容器做一下样式:

.container{
    width: 800px;
    height: 450px;
    margin: 20px auto;
    position: relative;
    background: rgb(187,235,255);
    border:1px solid #ddd;
    box-shadow:1px 1px 1px 1px rgba(0,0,0,0.1);
    overflow: hidden;
}

接下来分步讲解:
第一部分:天空,陆地
这部分就太简单了,最外层容器已经设置了天空的背景色,所以只需要将陆地的部分绘制出来就行了:

.load{
    position: relative;
    top:290px;
    background: rgb(27,121,160);
    height: 160px;
}

看一下效果:


第二部分:山脉,太阳,白云
首先是山脉的绘制,从上面的动图可以看到,山脉都是一些不同夹角的三角形状,那么其实我们制作的时候没必要说非得画出一模一样的形状出来,这里我都是绘制矩形,然后通过旋转来完成的,因为陆地在山脉上面,所以就遮掉了一部分,就能达到我们看到的效果,最关键的一点是夹角的度数问题,可以看到有锐角和钝角,这个我使用了skew()方法对矩形进行倾斜,然后旋转到合适的角度就达到我自己想要的效果了,第一块山脉代码如下:

.mountain .part_one{
    width:300px;
    height: 300px;
    background: rgb(106,207,255);
    position: absolute;
    -webkit-transform:rotate(30deg) skew(-20deg) translate3d(120px,200px,0);
    -moz-transform:rotate(30deg) skew(-20deg) translate3d(120px,200px,0);
    -o-transform:rotate(30deg) skew(-20deg) translate3d(120px,200px,0);
    -ms-transform:rotate(30deg) skew(-20deg) translate3d(120px,200px,0);
    transform:rotate(30deg) skew(-20deg) translate3d(120px,200px,0);
}

白云的话,这个就简单了,一个div加上两个伪元素就搞定,不多说,代码如下:

.cloud{
   display: inline-block;
   width: 40px;
   height: 40px;
   border-radius: 50%;
   background: #fff;
   position: absolute;
   left:-60px;
   top:20px;
}
.cloud:before{
   content: '';
   display: inline-block;
   width: 40px;
   height: 16px;
   border-radius: 16px 0 0 16px;
   background: #fff;
   position: absolute;
   bottom:0;
   left:-12px;
}
.cloud:after{
   content: '';
   display: inline-block;
   width: 40px;
   height: 28px;
   border-radius: 0 28px 28px 0;
   background: #fff;
   position: absolute;
   bottom:0;
   right:-16px;
}

太阳的制作主要还是太阳的光圈,这里我采用的是比较卡通的做法,显得比较可爱,而且形象地体现出天气阳光明媚。具体我使用了渐变背景,再加上一个阴影,然后实现动画效果,看起来有活力一些,代码如下:

.sun{
    position: relative;
}
.sun .center_sun{
    width:40px;
    height:40px;
    background: rgb(255,255,123);
    border-radius: 50%;
    position: absolute;
    top:-120px;
    right:160px;
}
.sun .sunshine{
    width:60px;
    height:60px;
    background: #f67e28; /* Old browsers */
    background: -moz-radial-gradient(center, ellipse cover, #f67e28 0%, #f67e28 50%, #f4bf9a 60%, #f4bf9a 100%); /* FF3.6+ */
    background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#f67e28), color-stop(50%,#f67e28), color-stop(60%,#f4bf9a), color-stop(100%,#f4bf9a)); /* Chrome,Safari4+ */
    background: -webkit-radial-gradient(center, ellipse cover, #f67e28 0%,#f67e28 50%,#f4bf9a 60%,#f4bf9a 100%); /* Chrome10+,Safari5.1+ */
    background: -o-radial-gradient(center, ellipse cover, #f67e28 0%,#f67e28 50%,#f4bf9a 60%,#f4bf9a 100%); /* Opera 12+ */
    background: -ms-radial-gradient(center, ellipse cover, #f67e28 0%,#f67e28 50%,#f4bf9a 60%,#f4bf9a 100%); /* IE10+ */
    background: radial-gradient(ellipse at center, #f67e28 0%,#f67e28 50%,#f4bf9a 60%,#f4bf9a 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f67e28', endColorstr='#f4bf9a',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
    position: absolute;
    top:-130px;
    right:150px;
    border-radius:50%;
    box-shadow: 0 0 2px 4px rgba(246,126,40,0.3);
}

效果图如下:


第三部分:房子和树
房子这一部分基本就是布局了,没什么难度,但是也有很多技巧,可让html结构更精简。
房子我分成房顶,旗子,墙,二楼,一楼:
1.墙:这是房子的基本,就是一个矩形,这里不赘述。
2.房顶:这里就是一个小正方形加上边框,旋转45度,也简单,不赘述。
3.旗子:难点其实在于旗面的五角星,比较烦,由于在场景中显示比较小,所以五角星的绘制不需要精准到位,大概形状像五角星就行,特别是旁边四个小星星。
4.二楼:我这里给二楼设置了高度,然后设置它的上下边框以实现一二楼的遮出层,窗户的话,要巧用两个伪元素,特别是窗户上面的遮篷部分,四个白色竖条就是使用两个伪元素的左右边框实现的。
5.一楼:一楼基本跟二楼差不多,门的绘制道理都相通,不赘述。
树的话,跟白云的绘制一样简单,不赘述。
效果图如下:

由于这一块的代码量有点多,我就不放上来了,直接到github下载吧。
第四部分:两辆汽车和石头
汽车本身的绘制关键也是使用了skew()方法,其他都是布局的问题,我就直接给代码:

.stone{
    width:30px;
    height: 16px;
    background: #333;
    border-radius: 16px 16px 5px 5px;
    position: absolute;
    top:410px;
    left:550px;
    box-shadow: 1px 1px 1px #333;
}
.car{
    position: absolute;
    left:900px;
    top:340px;
    z-index:12;
}
.car .car_body{
    position: absolute;
}
.car .car_top1,.car .car_top2{
    width:45px;
    height: 35px;
    border-top-left-radius:10px;
    border-top-right-radius:10px;
    background: rgb(246,126,40);
    position: absolute;
    left:0;
    top:0;
    -webkit-transform:skew(24deg);
    -moz-transform:skew(24deg);
    -o-transform:skew(24deg);
    -ms-transform:skew(24deg);
    transform:skew(24deg);
}
.car .car_top1{
    left:-29px;
    top:0px;
    -webkit-transform:skew(-24deg);
    -moz-transform:skew(-24deg);
    -o-transform:skew(-24deg);
    -ms-transform:skew(-24deg);
    transform:skew(-24deg);
}
.car .car_win1,.car .car_win2{
    width:24px;
    height:24px;
    background: #fff;
    border-top-left-radius:10px;
    position: absolute;
    left:13px;
    top:6px;
    -webkit-transform:rotate(80deg) skew(-10deg);
    -moz-transform:rotate(80deg) skew(-10deg);
    -o-transform:rotate(80deg) skew(-10deg);
    -ms-transform:rotate(80deg) skew(-10deg);
    transform:rotate(80deg) skew(-10deg);
}
.car .car_win1{
    left:-22px;
    -webkit-transform:rotate(0deg) skew(-10deg);
    -moz-transform:rotate(0deg) skew(-10deg);
    -o-transform:rotate(0deg) skew(-10deg);
    -ms-transform:rotate(0deg) skew(-10deg);
    transform:rotate(0deg) skew(-10deg);
}
.car .car_win1:after,.car .car_win2:after{
    content:'';
    display:inline-block;
    width:10px;
    height: 24px;
    background: #fff;
    position: absolute;
    left:16px;
    top:0;
    -webkit-transform:skew(10deg);
    -moz-transform:skew(10deg);
    -o-transform:skew(10deg);
    -ms-transform:skew(10deg);
    transform:skew(10deg);
}
.car .car_win2:after{
    top:9px;
    left:7px;
    -webkit-transform:rotate(-90deg) skew(-10deg);
    -moz-transform:rotate(-90deg) skew(-10deg);
    -o-transform:rotate(-90deg) skew(-10deg);
    -ms-transform:rotate(-90deg) skew(-10deg);
    transform:rotate(-90deg) skew(-10deg);
}
.car .car_bottom1,.car .car_bottom2{
    width:74px;
    height:33px;
    background: rgb(246,126,40);
    border-top-left-radius: 24px 20px;
    border-bottom-left-radius: 3px;
    border-bottom:8px solid rgb(186,188,187);
    position: absolute;
    top:34px;
    left:-66px;
    -webkit-transform:skew(-4deg);
    -moz-transform:skew(-4deg);
    -o-transform:skew(-4deg);
    -ms-transform:skew(-4deg);
    transform:skew(-4deg);
}
.car .car_bottom2:before{
    content: 'JR';
    font-size:12px;
    font-weight: bolder;
    color:#fff;
    position: absolute;
    top:5px;left:45px;
}
.car .car_bottom1:after{
    content: '';
    display: inline-block;
    background: rgb(247,244,111);
    width:10px;
    height: 16px;
    border-radius: 6px/8px;
    position: absolute;
    top:11px;
    left:6px;
}
.car .car_bottom2{
    height: 36px;
    border-top-left-radius: 0;
    border-top-right-radius: 13px 17px;
    border-bottom-right-radius: 3px;
    left:0px;
    top:31px;
    -webkit-transform:skew(8deg);
    -moz-transform:skew(8deg);
    -o-transform:skew(8deg);
    -ms-transform:skew(8deg);
    transform:skew(8deg);
}
.car .frontWheel,.car .endWheel{
    width:34px;
    height:34px;
    border-radius: 50%;
    background:#333;
    position: absolute;
    top:55px;
    left:-40px;
}
.car .endWheel{
    left:20px;
}
.car .frontWheel:after,.car .endWheel:after{
    content: '';
    display: inline-block;
    width:14px;
    height: 14px;
    background: #fff;
    border-radius: 50%;
    position: absolute;
    top:50%;
    left:50%;
    margin-top: -7px;
    margin-left: -7px;
}
.car .exhaust{
    width:18px;
    height:18px;
    background: rgba(0,0,0,0.3);
    border-radius: 8px 8px 8px 1px;
    position: absolute;
    left:80px;
    top:55px;
    opacity: 0;
}
.car2{
    position: absolute;
    left:900px;
    top:250px;
    z-index:10;
}
.car2 .car2_top{
    width:55px;
    height: 40px;
    border-top-left-radius:15px;
    border-top-right-radius:10px;
    background: rgb(117,191,135);
    position: absolute;
    left:-29px;
    top:0px;
    -webkit-transform:skew(-20deg);
    -moz-transform:skew(-20deg);
    -o-transform:skew(-20deg);
    -ms-transform:skew(-20deg);
    transform:skew(-20deg);
}
.car2_top:after{
    content: '';
    display: inline-block;
    width:12px;
    height: 40px;
    background: rgb(117,191,135);
    -webkit-transform:skew(20deg);
    -moz-transform:skew(20deg);
    -o-transform:skew(20deg);
    -ms-transform:skew(20deg);
    transform:skew(20deg);
    position: absolute;
    left:48px;
}
.car2 .car2_win{
    width:42px;
    height:30px;
    background: #fff;
    border-top-left-radius:10px;
    position: absolute;
    top:5px;
    left:-22px;
    -webkit-transform:rotate(0deg) skew(-20deg);
    -moz-transform:rotate(0deg) skew(-20deg);
    -o-transform:rotate(0deg) skew(-20deg);
    -ms-transform:rotate(0deg) skew(-20deg);
    transform:rotate(0deg) skew(-20deg);
}
.car2_win:after{
    content: '';
    display: inline-block;
    width:12px;
    height: 30px;
    background: #fff;
    -webkit-transform:skew(20deg);
    -moz-transform:skew(20deg);
    -o-transform:skew(20deg);
    -ms-transform:skew(20deg);
    transform:skew(20deg);
    position: absolute;
    left:36px;
}
.car2 .car2_bottom{
    width: 180px;
    height: 56px;
    background: rgb(117,191,135);
    border-top-left-radius: 50px;
    border-bottom-left-radius: 50px;
    position: absolute;
    top:39px;
    left:-60px;
}
.car2 .car2_bottom .car2_light1{
    width:14px;
    height: 20px;
    background: rgb(229,230,88);
    border-radius: 20px/30px;
    position: absolute;
    left:-3px;
    top:18px;
}
.car2 .car2_bottom .car2_light2,.car2 .car2_bottom .car2_light3{
    width:12px;
    height: 12px;
    background: rgb(229,230,88);
    border-radius: 50%;
    position: absolute;
    right:-8px;
    top:12px;
}
.car2 .car2_bottom .car2_light3{
    top:36px;
}
.car2 .car2_frontWheel,.car2 .car2_endWheel{
    width:40px;
    height:40px;
    background: #333;
    border-radius: 50%;
    position: absolute;
    top:75px;
    left:-30px;
}
.car2 .car2_endWheel{
    left:60px;
}
.car2 .car2_frontWheel:after,.car2 .car2_endWheel:after{
    content: '';
    display: inline-block;
    width:20px;
    height: 20px;
    background: rgb(216,107,82);
    border-radius: 50%;
    position: absolute;
    top:50%;
    left:50%;
    margin-left: -10px;
    margin-top: -10px;
}

主要还是讲解一下动画效果实现的原理:
1.浅绿色货车就没什么好说的了,直接改变left值,一直开过去就行了。
2.橙色汽车动画步骤分析:首先汽车比较快地从远处往餐厅方向开过来,不小心磕碰到路面上的石头,由于汽车速度有点快,惯性大,所以汽车后半身往上翘,同时汽车往前推行了一点点,当汽车掉下来的时候,由于重力的原因,车身会有缓动的效果,表现为掉落时车身向下压,然后回弹,此车司机撞懵了一下,然后重启汽车,开始汽车前行有点故障,然后过一小会就恢复正常,最后就开走了。大致思路就是这样,具体实现肯定是慢慢琢磨的过程了,要让动画效果合乎常理而又不失趣味性,才是真正考验的地方。

以上所有步骤完成了的话,那么久实现了最初预览时的效果了。
如果想学习整个案例的话,可以前往我提供的github地址下载:
https://github.com/JR93/cartoonAnimation

希望对大家学习CSS3有所帮助!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,113评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,644评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,340评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,449评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,445评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,166评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,442评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,105评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,601评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,066评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,161评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,792评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,351评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,352评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,584评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,618评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,916评论 2 344

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,033评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,525评论 25 707
  • 我不想说 是谁把谁错过 是谁的豪情被岁月消磨 又是谁 低着头 在寻找那已泯灭的焰火 我不想说 是谁游进了那条河 卷...
    East华阅读 235评论 0 0
  • 很久没有空摸一下的板子,拿出来时就控制不住自己的作品
    Minimalismaidai阅读 389评论 3 6
  • 两千里路河与山, 心中彼此时挂牵!
    行道子阅读 172评论 0 0