• 通过 js 给元素添加动画样式animation属性 ,以及 perspective 属性探究


    学习关键语句:
    js添加动画效果
    js控制元素animation属性

    写在前面

    在制作组件的过程中呢 , 突然觉得这个动画啊应该由用户来决定到底是个啥样 , 但是怎么让用户操作这一步呢 ? 总不能让用户自己去写 css keyframe 吧 , 所以便有了这篇文章 , 同时 , 这篇文章的下半部分我们会一起来看看 perspective 这个属性的效果 , 这个属性比较冷门 , 我也是第一次听说和使用 , 但是使用效果非常惊人 , 所以你先看看目录再说吧.

    出于适用性考虑 , 测试内容将使用新建的 html 文件来执行效果

    开始

    我们先写一个简单的页面 , 页面里面能看到的只有一个青色方块和一个按钮 , 我们将通过按钮赋予方块动画

    test.html

    <!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>test</title>
        <style>
            button {
                width: 120px;
                height: 40px;
                line-height: 40px;
                outline: none;
                position: absolute;
                left: 100px;
                top: 100px;
            }
            #dad {
                width: 300px;
                height: 500px;
                position: relative;
                top: 200px;
                left: 200px;
            }
            #son {
                width: 100%;
                height: 100%;
                background-color: cyan;
            }
        </style>
    </head>
    <body>
        <button onclick="addAnimate()"> 按我加动画 </button>
        <div id="dad">
            <div id="son"></div>
        </div>
    </body>
    <script>
        function addAnimate() {
     
        }
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    实现加动画的语句为 :
    元素.animate( [{ 关键帧 }] , { 普通的animation属性 } )
    注: 上面中此时的关键帧数组可直接改为关键帧对象

    元素.animate( [{ 关键帧 } , { 关键帧 }] , { 普通的animation属性 } )

    js 写法

    dom.animate(
    	// 关键帧数量大于1的时候必须要用数组包裹 , 只有一个关键帧时也可以使用数组包裹
    	{
    		width: '500px'
    	},
    	{
    		duration: 1000, // 持续时间
    		easing: 'linear', // 规定动画的速度曲线
    		delay: 0,// 在动画开始之前的延迟
    		iterations: Infinity,// 动画应该播放的次数
    		direction: "alternate", // 是否应该轮流反向播放动画
    		fill: 'forwards',// 动画是否停在最后一个关键帧
    	}
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    现在我们将按钮的事件补充完善

    addAnimate 方法

    function addAnimate() {
        document.getElementById('son').animate(
            [{
                width: '500px'
            }],
            {
                duration: 1000,
                easing: 'linear',
                delay: 0,
                iterations: 'Infinity',
                direction: 'alternate'
                fill: 'forwards',
            }
        )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    好的我们现在点击按钮就可以给元素添加动画效果了 , 我们一起来看一看截图
    在这里插入图片描述

    perspective 属性的学习使用

    关于 perspective 属性的学习来自于我阅读这篇文章
    https://www.cnblogs.com/yanggeng/p/11285856.html
    仅在这里做对我自己有利的整理和总结

    引入

    我们知道在现实世界中 , 我们看到的物体 , 在无光线折射的情况下 , 普遍存在近大远小的现象 , 一个物体在你眼中的大小和物体与你的距离有关 , 同一个物体在长度趋于无限时在你的眼中末端会消失 .

    但是 ,

    凡是写过 rotateY 属性的朋友们都知道 , 我们在做水平翻转的时候 , 实际上并没有出现近大远小的情况 , 反而给我们带来的直接视觉效果是元素的宽度一直在改变

    这个时候也许有的朋友就会说 , 因为浏览器默认的是使用2D效果 , 我们可以将它改为显示3D效果
    emmm你可以试试看 , 不过我测试来看得到的效果也不是理想的 , 需要试验的话请在上述 test.html文件添加以下样式

    * {
        transform-style: preserve-3d;
    }
    
    • 1
    • 2
    • 3

    测试 perspective 属性

    我们使用 perspective 属性来做到视觉上的近大远小 , 我们将上述文件中的 dad 元素样式添加

    • perspective :500px;

    将动画修改成水平翻转

    • transform: ‘rotateY(360deg)’

    test.html

    <!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>test</title>
        <style>
            button {
                width: 120px;
                height: 40px;
                line-height: 40px;
                outline: none;
                position: absolute;
                left: 100px;
                top: 100px;
            }
            #dad {
                width: 300px;
                height: 500px;
                position: relative;
                top: 200px;
                left: 200px;
                perspective :500px;
            }
            #son {
                width: 100%;
                height: 100%;
                background-color: cyan;
            }
        </style>
    </head>
    <body>
        <button onclick="addAnimate()"> 按我加动画 </button>
        <div id="dad">
            <div id="son"></div>
        </div>
    </body>
    <script>
        function addAnimate() {
            document.getElementById('son').animate(
                [{
                    transform: 'rotateY(360deg)'
                }],
                {
                    duration: 4000,
                    easing: 'linear',
                    iterations: 'Infinity',
                    // fill: 'forwards',
                    delay: 0,
                    // direction: 'alternate'
                }
            )
        }
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    perspective 属性值的选取

    通过学习上面提到的那篇文章我们可以得知两个关于 perspective 属性的信息

    1. perspective 属性必须写在父元素中 , 对子元素生效
    2. 属性值的本质是 从 你的眼睛 到 显示屏幕 的距离(单位 : px)

    我们知道近大远小 , 所以你离 显示 屏幕的距离越大 , 那么这个物体在你眼中的大小变化就会越小 , 我目前测试是使用 500px 可以获得一个比较好的显示效果

    perspective 属性值在 translateZ 存在情况下的异常 的 讨论

    注意:这是一个提示和警告
    在没有阅读学习文章(https://www.cnblogs.com/yanggeng/p/11285856.html)之前 , 你可能会对我这一小节说的内容存在疑惑 , 但是经过我的验证 , 原文中提到的现象是确实存在的 , 不过这里 , 我会提出和原文作者不同的猜想 , 希望大家如果有自己的想法可以疯狂 cue 我

    说的异常是什么?

    此处异常体现在 当子元素设定Z轴移动为 0px 时 , 即设定样式 transform: translateZ(0px);
    此时 , 无论设置 perspective 属性值为多少 , 元素的大小都不会再变化 ,
    同时 , 我发现还存在另一个异常 , 那就是
    此时无论是否开启 perspective 属性值 , 对于设定动画 X轴,Y轴,Z轴翻转都将不再生效

    你可以通过运行以下代码并在浏览器中检查元素直接修改 perspective 属性值来获得此处提到的异常

    <!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>test</title>
        <style>
            button {
                width: 120px;
                height: 40px;
                line-height: 40px;
                outline: none;
                position: absolute;
                left: 100px;
                top: 100px;
            }
            #dad {
                width: 300px;
                height: 500px;
                position: relative;
                top: 200px;
                left: 200px;
                perspective :500px;
            }
            #son {
                width: 100%;
                height: 100%;
                background-color: cyan;
                // 以下为新添加行
                transform: translateZ(0px);
            }
        </style>
    </head>
    <body>
        <button onclick="addAnimate()"> 按我加动画 </button>
        <div id="dad">
            <div id="son"></div>
        </div>
    </body>
    <script>
        function addAnimate() {
            document.getElementById('son').animate(null)
            document.getElementById('son').animate(
                [{
                    transform: 'rotateY(360deg)'
                }],
                {
                    duration: 4000,
                    easing: 'linear',
                    iterations: 'Infinity',
                    // fill: 'forwards',
                    delay: 0,
                    // direction: 'alternate'
                }
            )
        }
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    原文作者的解释

    原文作者解释道所谓元素 , 我们看到的实际上是真正元素在二维平面上的投影 , 所以当 Z轴移动样式为 0px 时 , 真正元素和他的投影重合在了 显示 屏幕上

    以上关于投影的说法我觉得有一定道理 , 因为可以使用投影的方式来修改任意元素显示在页面上的颜色和位置

    此时无论怎么改变我们的眼睛 到 显示屏幕 的距离(单位 : px)都无法影响到我们看到的元素大小 , 这也对原作者发现的异常算是有个合理的解释

    我的疑惑

    为什么我会有疑惑 , 因为我在使用 translate 属性时 , 如果设置的属性值为 0px , 那么元素的最终位置和初始位置在我眼中是相同的 , 以上意思是仅在我眼中是相同位置
    那么 , 如果说我们看到的元素是真正元素的投影 , 而且真正元素和看到的元素不在同一平面 , 那我们进行水平或者垂直移动并且设置好 perspective 属性值后应该会出现近大远小的现象 , 但是事实是并没有
    所以我大胆猜测 , 虽然我们看到的元素是真正元素的投影 , 但实际上他们在同一位置(空间上)

    我的猜想

    很明显 , 设置了样式 translateZ(0px) 和不设置给我们的效果是不一样的 , 是什么原因导致的呢 ?
    我给一个大胆的猜测 , 浏览器虽然默认以2D运行 , 但是在进行空间移动之前 , 可能 , 我是说可能 , 真正元素的位置并不存在 , 只是浏览器解析 html 文件后将元素的投影显示在了他应该在的位置 , 而进行移动之后 , 真正元素才会出现在画面之中(虽然感觉也很扯淡 , 但是反正只是不负责任的猜想 , 欢迎反驳)

    perspective-origin 属性的使用

    perspective-origin 这个属性是指你是从何视角进行观察的 , 默认是以中心视角 , 所以你运行的时候会发现 , 元素旋转的时候靠近你的上下两个角都会变大 , 是因为你的视角在中心 , 修改你的视角 , 你就会获得不一样的视觉效果
    这个属性值 包括两个值 一个是 X 轴的一个是 Y 轴的
    可选属性包括 百分比 , 距离(单位:px) , 位置(top , bottom , left , right)
    其中自己设定的位置以左上角为原点

    你可以在以下文件进行试验
    test.html

    <!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>test</title>
        <style>
            button {
                width: 120px;
                height: 40px;
                line-height: 40px;
                outline: none;
                position: absolute;
                left: 100px;
                top: 100px;
            }
            #dad {
                width: 300px;
                height: 500px;
                position: relative;
                top: 200px;
                left: 200px;
                perspective :500px;
                // 以下为新增属性
                perspective-origin:0px 0px;
            }
            #son {
                width: 100%;
                height: 100%;
                background-color: cyan;
            }
        </style>
    </head>
    <body>
        <button onclick="addAnimate()"> 按我加动画 </button>
        <div id="dad">
            <div id="son"></div>
        </div>
    </body>
    <script>
        function addAnimate() {
            document.getElementById('son').animate(
                [{
                    transform: 'rotateY(360deg)'
                }],
                {
                    duration: 4000,
                    easing: 'linear',
                    iterations: 'Infinity',
                    // fill: 'forwards',
                    delay: 0,
                    // direction: 'alternate'
                }
            )
        }
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    写在最后

    这个属性的探究确实让我感觉很多冷门的 CSS 样式其实非常有意思 , 而且很少见 , 写这篇花了不少心思 , 原文作者写的非常详细 , 希望了解这个属性的朋友一定要去看看原文 , 包括他的其他文章也很好理解
    感谢你的阅读 !

  • 相关阅读:
    卸载vs方法
    Eclipse 主网即将上线迎空投预期,Zepoch 节点或成受益者?
    SwiftUI 4 新功能 之 网格视图Gridview组件 (教程含源码)
    QT支持的平台
    中职组网络安全C模块全漏洞脚本讲解包含4个漏洞的脚本
    C++ | Leetcode C++题解之第50题Pow(x,n)
    搭建ELK+Filebead+zookeeper+kafka实验
    操作系统——进程和线程相关知识
    SL3037内置MOS管 耐压60V降压恒压芯片 降12V或降24V 电路简单
    用js写京东秒杀倒计时
  • 原文地址:https://blog.csdn.net/shaoyahu/article/details/128103683