CSS动画

146 阅读2分钟

transform实现动画,transform中的四个常用功能

位移translate:translate(x,y),translateX(x),translateY(y)等

        #demo {
            width: 100px;
            height: 100px;
            border:1px solid red;
            /* transition过渡属性可以自动补充中间帧 */
            transition: all 1s linear;
        }
        #demo.end {
            /* 元素在x轴方向向右平移200px */
            transform: translateX(200px);
        }

缩放scale:scale(x[,y]?)

        #demo:hover{
            /* 直接变大 */
            transform: scale(1.5);
        }

旋转rotate:rotate(angle)

        #demo:hover{
            /* 直接变大 */
            /* transform: scale(1.5); */
            /* 顺时针旋转 */
            transform: rotate(45deg);
        }

倾斜skew:skewX(angle),skewY(angle)

        #demo:hover{
            transform: skewX(15deg);
        }
  1. 一般都需要配合transition过渡
        #demo {
            width: 100px;
            height: 200px;
            border:1px solid red;
            margin:50px;
            /* 加动画效果 */
            transition:all 1s;
        }
  1. inline元素不支持transform,需要先变成block

绝对定位元素的居中

        #demo {
            width: 100px;
            height: 100px;
            border:1px solid red;
            position: absolute;
            /* 以下三行为重点,绝对居中的完美答案 */
            left:50%;
            top:50%;
            /* transform: translateX(-50%) translateY(-50%); */
            transform: translate(-50%,-50%);
        }
        .wrapper {
            border:1px solid black;
            position: relative;
            height: 500px;
        }
        
        <div class="wrapper">
            <div id="demo"></div>
        </div>

浏览器渲染原理

  • 浏览器渲染过程:
  • 根据HTML构建HTML树(DOM)
  • 根据CSS构建CSS树(CSSOM)
  • 将两棵树合并成一棵渲染树(render tree)
  • Layout布局(文档流、盒模型、计算大小和位置)
  • Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  • Compose合成(根据层叠关系展示画面)

如何更新样式

  • div.style.background = 'red'
  • div.style.display = 'none'
  • div.classList.add('red')
  • div.remove()直接删掉节点

三种不同的更新(渲染)方式

21.png

  • 第一种,全走:div.remove() 会触发当前消失,其他元素relayout
  • 第二种,跳过layout:改变背景颜色,直接repaint + composite
  • 第三种,跳过layout和paint:改变transform,只需composite。注意必须全屏查看效果,在iframe里看有问题

transform实现红心

<style>
        *{
            margin:0;
            padding:0;
            box-sizing: border-box;
        }
        #heart{
            margin: 100px;
            position: relative;
            display: inline-block;
            transition: all .5s;
        }
        #heart:hover{
            transform: scale(1.5);
        }
        #heart>.bottom{
            width:50px;
            height: 50px;
            /* border:1px solid red; */
            transform: rotate(45deg);
            background: red;
        }
        #heart>.left{
            width: 50px;
            height:50px;
            /* border:1px solid red; */
            background: red;
            border-radius: 50% 0 0 50%;
            position: absolute;
            bottom: 100%;
            right: 100%;
            transform: rotate(45deg) translateX(41px);
        }
        #heart>.right{
            width: 50px;
            height: 50px;
            /* border:1px solid red; */
            background: red;
            border-radius: 50% 50% 0 0;
            position: absolute;
            bottom: 100%;
            left: 100%;
            transform: rotate(45deg) translateY(41px);
        }
    </style>
    
    <body>
        <div id="heart">
            <div class="left"></div>
            <div class="right"></div>
            <div class="bottom"></div>
        </div>
    </body>

22.png

transition

作用:补充中间帧 过渡必须要有起始,一般只有一次动画,或者两次。比如hover和非hover状态的过渡

transition: 属性名 时长 过渡方式 延迟
transition: all 1s;

并不是所有属性都能过渡

  • display:none=>block没法过渡
  • 一般改成visibility:hidden=>visible
  • background颜色可以过渡
  • opacity透明度可以过渡
    <style>
        #demo {
            width: 100px;
            height: 100px;
            border:1px solid red;
            transition: all 1s;
            /* opacity: 1; */
            visibility: visible;
        }
        /* #demo:hover {
            width: 200px;
            height: 200px;
        } */
        #demo.end{
            width: 200px;
            height: 200px;
            /* opacity: 0; */
            visibility: hidden;
        }
    </style>
    
    <body>
        <div id="demo"></div>
        <button id="x">start</button>
    </body>
    <script>
        x.onclick = ()=>{
            demo.classList.add('end')
            // setTimeout(()=>{
            //     demo.remove()
            // },1000)
        }
        demo.ontransitionend = ()=>{
            demo.remove()
        }
    </script>
    
    

animation

animation:时长|过渡方式|延迟|次数|方向|填充模式|是否暂停|动画名

  1. 声明关键帧
  2. 添加动画
    <style>
        #demo {
            width: 100px;
            height: 100px;
            border:1px solid red;
            margin:50px;
        }
        /* 声明关键帧 */
        @keyframes xxx {
            0% {
                transform: none;
            }
            66.66% {
                transform:translateX(200px);
            }
            100% {
                transform: translateX(200px) translateY(100px);
            }
        }
        #demo.start{
            /* animation: xxx 1.5s forwards; */
            animation: 1.5s ease 1s infinite alternate forwards xxx ;
        }
        
    </style>
    
    <body>
        <div class="wrapper">
            <div id="demo"></div>
            <button id="button">开始</button>
            <button id="xxx">暂停</button>
            <button id="yyy">恢复</button>
        </div>
    </body>
    <script>
        button.onclick = ()=>{
            demo.classList.add('start')
        }
        xxx.onclick = ()=>{
            demo.style.animationPlayState = 'paused'
        }
        yyy.onclick = ()=>{
            demo.style.animationPlayState = 'running'
        }
    </script>

24.png

animation实现红心

    <style>
        *{
            margin:0;
            padding:0;
            box-sizing: border-box;
        }
        #heart{
            margin: 100px;
            position: relative;
            display: inline-block;
            /* transition: all .5s; */
            animation: heart 1s infinite alternate linear;
        }
        @keyframes heart {
            0% {
                transform: scale(1.0);
            }
            100%{
                transform: scale(1.5);
            }
        }
        /* #heart:hover{
            transform: scale(1.5);
        } */
        #heart>.bottom{
            width:50px;
            height: 50px;
            /* border:1px solid red; */
            transform: rotate(45deg);
            background: red;
        }
        #heart>.left{
            width: 50px;
            height:50px;
            /* border:1px solid red; */
            background: red;
            border-radius: 50% 0 0 50%;
            position: absolute;
            bottom: 100%;
            right: 100%;
            transform: rotate(45deg) translateX(41px);
        }
        #heart>.right{
            width: 50px;
            height: 50px;
            /* border:1px solid red; */
            background: red;
            border-radius: 50% 50% 0 0;
            position: absolute;
            bottom: 100%;
            left: 100%;
            transform: rotate(45deg) translateY(41px);
        }
    </style>
    
    <body>
        <div id="heart">
            <div class="left"></div>
            <div class="right"></div>
            <div class="bottom"></div>
        </div>
    </body>
    

23.png

资料来源:饥人谷