css动画 基础实用教程

263 阅读1分钟

1、基本操作

  • 旋转操作

  • 模块

2、 回流(重排)和 重绘

3、动画基础(transition)

4、动画基础(animation)

5、时间函数详解和举例

  • 例子 html部分

<div class="loading">
   </div>

css部分

 .loading {
            width: 64px;
            height: 64px;
            background: url(./imgs/loading.jpg) no-repeat;
            animation: load 2s steps(12) infinite;
        }
        
        @keyframes load {
            100% {
                transform: rotate(360deg);
            }
        }
  • 注意 steps(12) 这个写12 因为 图片有12个小格子

  • 实现效果 转起来 比较漂亮的 loading

6、动画状态的监听和思考

html

<div class="loading"></div>

css

.loading {
        width: 64px;
        height: 64px;
        background: url(./imgs/loading.jpg) no-repeat;
        animation: load 2s steps(12) 2;
      }

      @keyframes load {
        100% {
          transform: rotate(360deg);
        }
      }

js

let $loading = document.querySelector(".loading");
    //监听 动画开始
    $loading.addEventListener("animationstart", () => {
      console.log("runstart");
    });
    //监听动画结束
    $loading.addEventListener("animationend", () => {
      console.log("runend");
    });
    //监听动画的重复 用的比较少
    $loading.addEventListener("animationiteration", () => {
      console.log("iteration");
    });

  • 在另外一个例子 transition.html中监听

7、实践篇

7-1 、落雨到红包雨实现

思路
1、落雨 是先加速后减速的过程
2、先写一个雨滴,再写其他的雨滴
  • 代码 拿走不谢
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body,
      html {
        width: 100%;
        height: 100%;
      }
      .content {
        position: relative;
        background: #f2f2f2;
        height: 100%;
        overflow: hidden;
      }
      .content .yudi {
          /* 第一个雨滴定位住 */
        position: absolute;
        width: 4px;
        height: 6px;
        background: #ccc;
        clip-path: ellipse(10% 30% at 50% 50%);
        /* 放大/缩小 */
        transform: scale(6);
        /* 现在 不知道选什么时间函数  暂且勇 ease-in占位 */
        animation: drops 1.2s cubic-bezier(0.54, 0, 0.18, 0.34) infinite;

        /* 动画未启动时,不可见 */
        opacity: 0;
      }

      @keyframes drops {
        0% {
          opacity: 0;
        }
        20% {
          opacity: 1;
        }
        90% {
          opacity: 1;
        }
        100% {
          opacity: 0;
          /* x y z 方向  */
          /* 1.vw:1vw等于视口宽度的1%。
        2.vh:1vh等于视口高度的1%。 */
          transform: translate3d(10px, 100vh, -10px);
        }
      }
    </style>
  </head>
  <body>
    <div class="content">
      <div class="yudi"></div>
    </div>
  </body>


  <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
  <script>
    //   使用jq 选中 content
      let $content = $('.content')
    // 初始化雨滴数
    let initNumber = 0;
    for(let i=0; i < 30; i ++){
        let lefts = Math.floor(Math.random()* 5 + 2)
        // 延时参数  记得Math.random() 后面一定记得加上括号
        let delay = Math.floor(Math.random() * 50 + 2)
        initNumber += lefts
        // jq创建一个 div 并使用 addClass添加class
        // 使用 .css 写效果 分布开
        let $div = $('<div/>').addClass('yudi').css({
            'left' :`${initNumber}%`,
            'top' : `${lefts}%`,
            // 设置延时
            'animation-delay' : `${delay/10}s`
        })
        // 将创建的div 添加到页面
        $content.append($div)
    }
</script>

  </script>
</html>

  • 升级为红包雨

7-2 js配合动画属性实现图片无限滚动

  • 直接看代码吧 标注比较仔细了
 <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .marquee {
            overflow: hidden;
        }
        
        .content {
            display: flex;
            flex-direction: row;
        }
        
        .list {
            /* overflow: hidden; */
            display: flex;
        }
    </style>
</head>

<body>
    <!-- 这个标签可实现 从右往左不断循环滚动 -->
    <!-- <marquee behavior="" direction=""><img src="./imgs/tuzi.jpeg" alt=""></marquee> -->
    <div class="marquee">
        <div class="content">
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
        </div>
    </div>
</body>

<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>
<script>
    // jq 挂载
    $(() => {
        console.log('页面元素加载完成后执行这里面的内容')
            // 使用jq 选择需要的元素
        var outerWidth = 600,
            outerHeight = 400,
            speed = 3
        var $marquee = $('.marquee')
        var $content = $marquee.find('.content')
        var $list = $content.find('.list')
        var listLength = $list.length
        var contentWidth = outerWidth * listLength

        // 获取样式表
        var style = document.styleSheets

        // 给最外层 $marquee 尺寸 上面需要声明使用的变量
        $marquee.css({
            "width": `${outerWidth}px`,
            "height": `${outerHeight}px`
        })

        // 需要设定 list尺寸 
        $list.css({
            "width": `${outerWidth}px`,
            "height": `${outerHeight}px`
        })

        // 计算得到 content尺寸
        $content.css({
            "width": `${contentWidth}px`,
            "height": `${outerHeight}px`,
            // 动画效果 
            "animation": `run ${speed * listLength}s linear infinite`
        })
        style[0].insertRule(`
        @keyframes run{
            100%{transform:translateX(-${contentWidth}px)}
        }`)

        // 克隆 作用是不断连续的滚动  不会滚动一次就停止
        var clone = $list.eq(0).clone()
        $content.append(clone)
    })
</script>

</html>

7-3 transition 实现轮播效果

  • 效果比较完整 可以试试哈
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .marquee {
            overflow: hidden;
        }
        
        .content {
            display: flex;
            flex-direction: row;
        }
        
        .list {
            /* overflow: hidden; */
            display: flex;
        }
    </style>
</head>

<body>
    <!-- 这个标签可实现 从右往左不断循环滚动 -->
    <!-- <marquee behavior="" direction=""><img src="./imgs/tuzi.jpeg" alt=""></marquee> -->
    <div class="marquee">
        <div class="content">
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
            <div class="list"><img src="./imgs/tuzi.jpeg" alt=""></div>
        </div>
    </div>
    <button id="preBtn">
        << pre </button> <button id="nextBtn"> next >>
    </button>
</body>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js">
</script>
<script>
    // jq 挂载
    $(() => {
        console.log('页面元素加载完成后执行这里面的内容')
            // 使用jq 选择需要的元素
        var outerWidth = 600,
            outerHeight = 400,
            speed = 3,
            initIndex = 0,
            setTimeId = null,
            transitionTime = 0.1
        var $marquee = $('.marquee')
        var $content = $marquee.find('.content')
        var $list = $content.find('.list')
        var listLength = $list.length
        var contentWidth = outerWidth * listLength

        // 获取样式表
        var style = document.styleSheets

        // 给最外层 $marquee 尺寸 上面需要声明使用的变量
        $marquee.css({
            "width": `${outerWidth}px`,
            "height": `${outerHeight}px`
        })

        // 需要设定 list尺寸 
        $list.css({
            "width": `${outerWidth}px`,
            "height": `${outerHeight}px`
        })

        // 计算得到 content尺寸
        $content.css({
                "width": `${contentWidth}px`,
                "height": `${outerHeight}px`,
                // 动画效果 
                // "animation": `run ${speed * listLength}s linear infinite`
            })
            //运动
            // style[0].insertRule(`
            // @keyframes run{
            //     100%{transform:translateX(-${contentWidth}px)}
            // }`)

        // 克隆 作用是不断连续的滚动  不会滚动一次就停止
        var clone = $list.eq(0).clone()
        $content.append(clone)

        // 需要无限的轮询播放
        function autoPlay() {
            // 上面初始化这个地方使用 ++ 

            setTimeId = setInterval(() => {
                initIndex++
                // 移动 content
                $content.css({
                    "transition": `transform ${transitionTime}s ease`,
                    "transform": `translateX(-${outerWidth * initIndex}px)`
                })
                initIndex === listLength ? initIndex = 0 : ''
            }, speed * 1000)


        }
        // autoPlay()

        // 最后一张图片到第一张图片 切换有跳动效果  怎么处理?
        $content[0].addEventListener('transitionend', () => {
            $content.css({
                "transition": `none`,
                "transform": `translateX(-${outerWidth * initIndex}px)`
            })
        })
        $('#preBtn').mouseenter(() => {
            if (initIndex === 0) {
                initIndex = listLength
                $content.css({
                    "transition": `none`,
                    "transform": `translateX(-${outerWidth * initIndex}px)`
                })
            }
        })
        $('#preBtn').click(() => {
            // console.log('pre clicked')
            initIndex === 0 ? initIndex = listLength : ''
            initIndex--
            // 移动 content
            $content.css({
                "transition": `transform ${transitionTime}s ease`,
                "transform": `translateX(-${outerWidth * initIndex}px)`
            })

        })

        $('#nextBtn').click(() => {
            // console.log('next clicked')
            initIndex++
            // 移动 content
            $content.css({
                "transition": `transform ${transitionTime}s ease`,
                "transform": `translateX(-${outerWidth * initIndex}px)`
            })
            initIndex === listLength ? initIndex = 0 : ''
        })
    })
</script>

</html>