整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

html打造动画小猫笑脸动画

咪容器

  • 咱们每次画一个图片,肯定先要确定一个容器,几确定一下图形的位置和大小。

    <div class="mao_box">

画喵咪的头部和头部的花纹

  • 按照绘画习惯,我们肯定是先画最大的头部,头部确定了,耳朵嘴巴的位置才能确定。

    <!-- 猫咪的头部框架 -->

  • 猫咪头部.png

画猫咪的耳朵部分

  • 猫咪的耳朵分布在头部的左右两边,所以肯定是由两个div画成,为了不显得那么僵硬,我们可以把两边的耳朵稍微画的不一样大。

  • 大家肯定会想:耳朵的形状这么奇怪,到时是怎么画的呢?其实很简单,就是通过矩形然后设置各个角度的border-radius就会形成一种尖角的效果,再旋转相应的角度跟头部贴合就可以了。

  • 最后将耳朵隐藏在脸部的后面,露出一点点耳尖就可以了。

    <!--绘制耳朵的容器-->

  • 耳朵.jpg

画猫咪的眼睛部分

  • 眼睛部分有点复杂哟,不经过仔细的一番研究和强大的想象力是很难画出来的:解剖一下就是上下两个椭圆重叠而成,多余的部分隐藏,中间的褐色眼珠是在上面圆形中的一个黑色矩形。

    <div class="yanjing">

  • 猫咪眼睛.jpg

画猫咪的脸部花纹

  • 喵咪的胡须可是很重要的哟,如果不小心把它剪了可是很严重的,猫咪就再也无法测量自己可以钻进多大的洞里了,哈哈。

  • 仔细观察花纹其实就是由左右各5条线条组成,画出线条再做相应的变换就可以了。

    <div class="face_huawen">

  • 猫咪脸部花纹.jpg

画猫咪的鼻子

  • 感觉这是整个猫咪最好画的地方了,简单的一个半圆就可以解决问题啦~啦啦啦啦~

    <div class="bizi">

  • 猫咪的鼻子.png

画猫咪的嘴巴

  • 咦?是不是感觉画着画着就到了最后一部分了,哈哈哈哈哈,好开心啊~又吃成长快乐了~

  • 嘴巴就像两撇小胡子,用两个矩形边框就可以实现了。

    <div class="zuiba_box">

  • 猫咪嘴巴.jpg

各个部位拼接成一个完整的小猫

  • 各个部位都画好之后,又到了像大白一样的拼图时间了,哈哈~大家一起拼出一个萌萌哒小猫吧~(主要是对transition属性的运用,设置:hover之后的属性,然后用transition设置属性完成变化的过渡时间)

  • 拼图咯--哈哈.jpg

制作鼠标移动上去的动态效果

  • 我们家毛球可是个动如脱兔的家伙哦,所以我们来给猫咪加点特效吧~(^__^)

  • 鼠标移动上去之后两耳耳朵左右摆动

  • 眼睛眯眯呈现笑脸的形状

PS:眼睛眯起来之后下面出现了一部分红晕,就是两个背景颜色半透明的小椭圆组成的,只要在鼠标移动上去只会把椭圆显示出来就可以了。

眼睛下面的红晕.png

  • 嘴角上扬

    /*鼠标浮动耳朵样式*/.mao:hover .erduo > div:first-child { left: -10px; transform: rotate(0deg); -ms-transform: rotate(0deg); -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -o-transform: rotate(0deg); border-radius: 4% 80% 0% 60%;

学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入学习交流群

343599877,我们一起学前端!

近大家刷抖音,是否有刷到拉斯维加斯的新地标 「Sphere」:

场馆内部的视觉效果非常惊人,其中一个效果让我虎躯一震:

我的第一想法就是,这个看起来用 CSS 也可以实现嘛?还有 CSS 不能实现的?

本文,就将尝试使用 CSS,大致还原这个效果。

拆解动画效果

其实,上述的动画效果,本质就是一个 3D 立方体。

同时,3D 立方体上每个面存在颜色不一样的文字,文字和颜色都在随机变化。

也就是说,我们需要实现一个 3D 立方体:

同时,我们还需要实现这样一个动画效果 -- 文字和颜色都在随机变化的平面效果:

两者组合一下,再挪动 3D 元素的景深距离,就能实现我们想要的效果!

好,下面我们一个一个实现。

实现一个 3D 立方体

实现一个 3D 立方体,相对另外一个文字和颜色都在随机变化的平面效果而言,属于非常非常简单的一步了。

我们在非常多篇文章中也讲过具体的实现方式:

最常见的 3D 图形,莫过于一个 3D 立方体。

如果没有上下两个面,只是一个 4 个面的图形,大概是这样:

这样一个图形,利用 CSS 3D,如何快速实现呢?

首先,构造这么一个结构:

<div class="perspective">
        <div class="container">
                <div class="img">3</div>
                <div class="img">D</div>
                <div class="img">视</div>
                <div class="img">图</div>
        </div>
</div>

4 个面,就是最内层的 4 个 .img,首先,需要给两个父容器,设置 3D 的属性:

.perspective {
  perspective: 3000px;
}
.container {
  width: 400px;
  height: 400px;
  transform-style: preserve-3d;
}

简单解释一下:

  1. perspective 可以作用于元素的后代,设置在最上层即可;
  2. transform-style: preserve-3d 设置给最终需要 3D 空间的元素的父容器之上,由于最终是 4 个 .img 需要 3D 空间,因此设置给 .container 即可。

接下来,就是最为核心的,如何设置 4 个 .img 元素的 3D 变换,使之形成 3D 立方体。

技巧就是:先旋转,再位移

这里给出一个俯视效果图:

以上述 Demo 中的正方体为例子,class 为 .img 的 div 块的高宽为 400px*400px。那么要利用 4 个 这样的 div 拼接成一个正方体,需要分别将 4 个 div 绕 Y 轴旋转 [90°, 180°, 270°, 360°],再 translateY(200px) 。

值得注意的是,一定是先旋转角度,再偏移距离,这个顺序很重要

代码如下:

.img {
        position: absolute;
        top: 0;
        left: 0;
        width: 400px;
        height: 400px;
}
@for $i from 1 through $imgCount {
        .img:nth-child(#{$i}) {
                transform: rotateY(($i * 90deg)) translateZ(200px);
        }
}

效果如下:

此时,可能会觉得图片太太太大了,此时,我们可以通过给中间层 .container 设置一个恰当的 translateZ 进行视觉大小上的调节。

.container {
    transform: translateZ(-3000px);
}

这样,就能得到恰当大小的立方体元素效果:

当然,对于我们这个效果,我们 5 要五个面(前后左右与上方即可),因此,我们基于上述的基础知识铺垫,重新实现一个我们需要的框架结构:

<div class="perspective">
  <div class="container">
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
  </div>
</div>

并且,我们希望我们的图形是一个立方体,只需要稍微改造长宽和 translateZ() 的即可。这样,我们就能得到一个前后左右与上方 5 个面的立方体元素。

示意效果如下:

实现文字动画效果

OK,立方体我们先放在一边。

接下来,我们尝试来实现这个效果:

这个效果如果一个文字用一个 DIV 承载实现,那是非常容易的,但是这样势必会造成元素过多,再设置动画效果,则会导致页面太为卡顿

所以,我们需要另辟蹊径。这里,我们可以使用多层渐变配合 background-clip: text

首先,我们利用等宽字体,随机实现一列文字:

<div>ABCDEFGHIJKLMN</div>
div {
    font-family: monospace;
    text-align: center;
    font-size: 25px;
    width: 25px;
    line-height: 25px;
    color: #fff;
}

效果大致如下:

此时,如果我们再利用线性渐变,给每个字符的对应空间(也就 25px x 25px),设置上不同的颜色,大概是这样:

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}
div {
    // ...
    background: randomLinear(14);
}

其中,randomLinear(14) 是一个 SASS 函数,参数 14 表示生成 14 层线性渐变,每一个文字区域的颜色都是随机的,经过编译后的其中一种结果如下:

div {
    // ...
    background: linear-gradient(#feea96 0 25px, #edde42 0 50px, #e2344a 0 75px, #cdab7e 0 100px, #e16c8b 0 125px, #dcdc7d 0 150px, #dcb42a 0 175px, #d6a587 0 200px, #984f71 0 225px, #221e34 0 250px, #5e9a69 0 275px, #a955e4 0 300px, #4e908f 0 325px, #8d177e 0 350px);
}

上面,我们按照每间隔 25px 的高度,利用线性渐变随机设置了一种颜色,最终,能够得到这么个效果:

此时,我们只需要再设置 background-clip: text,配合透明文字颜色 color: transparent,就可以实现单个 div 内,单列文字,每个字体的颜色都是不一样的:

div {
    // ...
    background: randomLinear(14);
    background-clip: text;
    color: transparent;
}

此时,效果如下:

当然,文字颜色可以随机,那么文字本身也应该随机。这个不难,我们也可以借助 SASS 函数,编写一个随机字符的函数,通过元素的伪元素 content 进行设置。

那么此时,完整的代码可能是这样的:

<div></div>
$str: 'QWERTYUIOPASDFGHJKLZXCVBNMabcdefghigklmnopqrstuvwxyz123456789';
$length: str-length($str);

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}
@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}
@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

div {
    position: relative;
    width: 25px;
    height: 350px;

    &::before {
        content: randomChars(14);
        position: absolute;
        font-family: monospace;
        background: randomLinear(14);
        background-clip: text;
        color: transparent;
        text-align: center;
        font-size: 25px;
        width: 25px;
        line-height: 25px;
    }
}

这样,每次 div 内的文字,都是从上面 SASS 函数中 $str 变量中随机取的:

接下来,我们需要实现文字的随机跳变,也很好做,我们需要在一开始,随机生成多个不同的 content,然后,借助 CSS 动画,进行切换。

div {
   &::before {
        content: randomChars(14);
        --content1: "#{randomChars(14)}";
        --content2: "#{randomChars(14)}";
        --content3: "#{randomChars(14)}";
        --content4: "#{randomChars(14)}";
        animation: contentChange 1s infinite;
    }
}

@keyframes contentChange {
    20% {
        content: var(--content1);
    }
    40% {
        content: var(--content2);
    }
    60% {
        content: var(--content3);
    }
    80% {
        content: var(--content4);
    }
}

这里,我们一次生成了 5 个 content,其中 4 个用 CSS 变量保存了起来,随后,在 CSS 动画中,利用提前生成好的 content,进行字符内容的替换,此时,整个效果如下:

随机内容有了,单个字体颜色不一样有了,就差颜色的随机跳变动画了,这个也非常好做,我们在多篇文章也提及过,利用 filter: hue-rotate() 可以快速实现内容的颜色切换。

div {
    animation: colorChange 1s steps(12) infinite;
}
@keyframes colorChange {
    100% {
        filter: hue-rotate(360deg);
    }
}

我们利用了 filter: hue-rotate() 加上了步骤动画(steps),成功的实现了颜色的跳变!效果如下:

当然,我们最终要实现的是整个面随机颜色加上随机文字的跳变动画,只需要在上述的基础上,利用 SASS 函数,循环重复多列操作即可。基于上述所有内容的铺垫,我们最终的单个面下的动画效果代码如下:

<div class="g-container">
  <div></div>
  // ... 一个 32 个子 div
  <div></div>
</div>
@use "sass:string";

$str: 'QWERTYUIOPASDFGHJKLZXCVBNMabcdefghigklmnopqrstuvwxyz123456789';
$length: str-length($str);
$size: 25;
$count: 41;

@function randomNum($max, $min: 0, $u: 1) {
    @return ($min + random($max)) * $u;
}

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}

@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}

@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}

@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

body,
html {
    width: 100%;
    height: 100%;
    background: #000;
    font-family: monospace;
}

.g-container {
    position: relative;
    width: 800px;
    height: 800px;
    display: flex;
    animation: colorChange 1s steps(12) infinite;
    
    div {
        position: relative;
        width: #{$size}px;
        height: 800px;
        flex-shrink: 0;
        
        &::before {
            position: absolute;
            inset: 0;
            text-align: center;
            font-size: #{$size}px;
            width: #{$size}px;
            text-align: center;
            line-height: #{$size}px;
            color: transparent;
        }
    }
    
    @for $i from 1 to $count {
        div:nth-child(#{$i}) {
            &::before {
                content: randomChars(32);
                --content1: "#{randomChars(32)}";
                --content2: "#{randomChars(32)}";
                --content3: "#{randomChars(32)}";
                --content4: "#{randomChars(32)}";
                animation: contentChange 1s infinite;
                background: randomLinear(32);
                background-clip: text;
            }
        }
    }
}
@keyframes colorChange {
    100% {
        filter: hue-rotate(360deg);
    }
}
@keyframes contentChange {
    20% {
        content: var(--content1);
    }
    40% {
        content: var(--content2);
    }
    60% {
        content: var(--content3);
    }
    80% {
        content: var(--content4);
    }
}

这样,我们就成功的实现了单个平面下的,颜色随机,文字随机,且不断变化的动画效果:

实现立体效果

有了上面的立方体和单个平面的效果,要实现立体效果就不难了。我们尝试将两者结合起来。

改造原有的立方体结构,大致改成如下形式:

.perspective
    .container
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div

上面采用了 PUG 模板引擎来简化代码,编译后的效果如下:

<div class="perspective">
  <div class="container">
    <div class="g-panel">
      <div></div>
      // ... 32 个
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 个
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 个
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 个
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 个
      <div></div>
  </div>
</div>

这里,我们只需要实现 5 个面的立方体即可(前后左右以及上方)。

每个 .g-panel,实现一个我们上面铺垫的单面文字跳变效果,这样,我们就能得到这么一个立体的 3D 立方体动画效果:

接下来,我们只需要稍加调试,通过控制 perspective 和 transform: translateZ() 控制视觉上的纵深,将画面的视角放置于整个立方体之中,即可得到这么个效果:

好,最后,我们模拟文章开头拉斯维加斯球的效果,让顶部的平面,向下运动,实现一种天花板往下掉的动画效果,最终,我们即可使用纯 CSS,大致模拟出整个效果:

由于 GIF 录制问题,实际效果会比 GIF 展示效果更为震撼。


、关于css3的transition属性:

transition:翻译为“过渡”,过渡是一个持续性的动作,因此必须定义一个持续时间。

transition属性:

1.transition-property属性:指定CSS属性的过渡效果,常用于鼠标悬停在一个元素上时指定属性的变化效果

none:没有属性会获得过渡效果。

all:所有属性都会获得过渡效果,此值为默认值

<property>:指定属性获得过渡效果,多个属性用逗号分隔,如 width,color

2.transition-duration属性:规定完成过渡效果需要花费的时间(以秒或毫秒计,如: 0.5s),如需要过渡效果,必须指定一个过渡时间,否则过渡效果是不会生效的;

3.transition-timing-function属性:指定切换效果的速度,此属性允许一个过渡效果,以改变其持续时间的速度;

linear 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。
ease (默认值) 规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezier(0.25,0.1,0.25,1))。
ease-in 规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))。
ease-out 规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))。
ease-in-out 规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))。
cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。

4.transition-delay 属性:指定何时将开始切换效果,延迟一段时间后触发过渡(以秒或毫秒计,如: 0.5s),默认为0s

除了transition-duration属性外,其他都有默认值,如果不需要改变默认值可以不指定,只配置transition-duration属性即可:

transition:0.5s 等价于 transition: all 0.5s ease 0s;

例:针对的是一个标签元素

div{
   width: 100px;
   height: 100px;
   background-color: wheat;
 
   //当div的width属性发生变化时,应用此过渡效果
   transition: width 0.5s ease 0s; 
}
//鼠标指向时div的width属性发生变化
div:hover{
   width:300px;
}
 
<div></div>

二、关于css3的transform属性:

transform 属性:应用于元素的2D或3D转换,这个属性允许你将元素旋转,缩放,移动,倾斜等。

translate(x,y)、translateX(x)、translateY(y):定义2D转换,x.y单位一般取px,transform:translateX(100px):元素相对原本位置之右100px

div{
  //div相对原来位置在右下100px处
  transform:translate(100px,100px)
}

scale(x,y)、scaleX(x)、scaleY(y),在2D上旋转绽放

rotate(x,y)、rotateX(x)、rotateY(y),在2D上旋转

skew(x,y)、skewX(x)、skewY(y),在2D上倾斜

三、关于Vue的过渡动画

开启vue过渡动画,只需要将需要开启的标签放到<transition>中,同时标签使用v-if控制显示和隐藏。

<input type="button" value="点击" @click="isShow=!isShow" >
<transition>
    <p v-show="isShow">{{msg}}</p>
</transition>

vue的过渡进程图:针对的是类名


进入前、进入后、离开前、离开后,四个状态是一个点,而v-enter-active v-leave-active是一个持续的状态,因此,active中需要标明持续的时间,

v-enter、v-enter-to、v-leave、v-leave-to:需要定义四个状态点的属性:

.v-enter-active,
.v-leave-active {
   //过渡持续时间0.6秒
   transition:  0.6s;
}
 
.v-enter,
.v-leave-to {
     //进入前、离开后,完全透明
     opacity: 0;
     //进入前,离开后,元素相对位置在下边100px处
     transform:translateY(100px);
}
 
.v-enter-to,
.v-leave {
   //进入后、离开前,完全不透明
    opacity: 1;
}

四、自定义前缀

当在<transition name="fade">指定了name属性,就可以使用前缀 .fade-enter 这样。

五、使用第三方animate.css来实现动画

1.引入animate.css

<link ref="stylesheet" href="animate.css">

2.在<transition>中增加enter-active-class和leave-active-class,类名可以通过官方网站复制

官方网站:https: //animate.style/


<input type="button" value="点击" @click="isShow=!isShow" >
<transition  enter-active-class="animate__bounceIn" leave-active-lass="animate__bounceOut">
    <p v-show="isShow" id="p">{{msg}}</p>
</transition>

六、列表动画演示