高中物理学运动公式实现js动画

高中物理学运动公式实现js动画js动画

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

在网页上创建动画一般有两种方式:css和javascript。它们在创建动画的时间和性能上是不一样的,各有利弊。选择哪种方法实际上取决于项目,以及想要实现什么类型的动画。

一般使用css动画来实现比较简单的“一次性转换”,为UI元素转换比较小的独立状态。例如从侧面引入导航栏菜单,模太框弹出等。
要实现高级效果时,例如弹跳,加速,减速等比较复杂的动画,则使用Javascript动画。现在有很多比较好的JS动画框架,例如TweenMax,Velocity,animo.js,jquery。

不管是css还是javascript来创建动画,我们都会听到一个词“缓动”。自然界中没有东西从一点呈线性的移动到另一点,一般可能需要加速或减速。在经典动画中,经常会出现“缓入”,“缓出”,“缓入缓出”效果。缓动使动画不再那么尖锐或生硬。
css中,我们要想达到这些效果,只需要使用一些关键字:
* linear
* ease-in
* ease-out
* ease-in-out

那这么关键字的背后到底是什么原理呢?如何用javascript来实现这些缓动效果。

动画是关于时间的函数,本质就是利用浏览器和GPU的渲染过程定时改变元素的属性。

使用javascript实现动画时一般是使用requestAnimationFrame,我们可能经常也会用setInterval和setTimeout来实现动画,但是它们实现的动画都不会与屏幕的刷新率同步,并且很可能出现抖动和跳帧,例如jQuery就是采用setInterval来实现动画,所以jQuery动画的帧率会偏低(jQuery为甚么不采用RAF)。

“Talk is cheap, show me the code”。下面学习实现下月影总结的动画原理。原理简单,实现经典。

常见运动

  1. 匀速运动

    让小球在2s内向右匀速移动200px

    • 时间: t = T * p
    • 位移: St = S * p = v * t
    • 速度: v = St / t = S / T
    • 加速度: a = 0
circle.on('click', function() { 
   
    var self = this;
    var startTime = Date.now();
    var distance = 200;
    var T = 2000;
    requestAnimationFrame(function step() { 
   
        var p = Math.min(1.0, (Date.now() - startTime) / T);
        self.style.transform = 'translateX(' + (distance * p) + 'px)';
        if(p < 1.0){
            requestAnimationFrame(step);
        }
    })
})

匀速运动

2.匀加速运动

让小球在2s内向右匀加速向右移动200px, 速度从0开始
* 时间: t = T * p
* 位移: St = S * p^2 = (S * t^2) / T^2
* 速度: v = (2*S / T^2) * t = 2Sp/T
* 加速度 a = 2*S / T^2

circle.on('click', function() { 
   
        var self = this;
        var startTime = Date.now();
        var distance = 200;
        var T = 2000;
        requestAnimationFrame(function step() { 
   
            var p = Math.min(1.0, (Date.now() - startTime) / T);
            self.style.transform = 'translateX(' + (distance * p * p) + 'px)';
            if(p < 1.0){
                requestAnimationFrame(step);
            }
        })
    })

匀加速

3.匀减速运动

让小球在2s内向右匀减速向右移动200px, 速度从最大减为0
* 时间: t = T * p
* 位移: St = (2*S / T) * t – (S / T^2) * t^2 = Sp * (2 – p)
* 速度: v = 2*S / T – 2*S / t^2 * t
* 加速度 a = -2*S / T^2

circle.on('click', function() { 
   
        var self = this;
        var startTime = Date.now();
        var distance = 200;
        var T = 2000;
        requestAnimationFrame(function step() { 
   
            var p = Math.min(1.0, (Date.now() - startTime) / T);
            self.style.transform = 'translateX(' + (distance * p * (2 - p)) + 'px)';
            if(p < 1.0){
                requestAnimationFrame(step);
            }
        })
    })

匀减速

4.抛物线运动

circle.on('click', function() { 
   
    var self = this;
    var startTime = Date.now();
    var disX = 200, disY = 200;
    var T = 1000 * Math.sqrt(2 * disY / 98);
    requestAnimationFrame(function step() { 
   
        var p = Math.min(1.0, (Date.now() - startTime) / T);

        var tx = disX * p;
        var ty = disY * p * p;
        self.style.transform = 'translate(' + tx + 'px, ' +ty +  'px)';
        if(p < 1.0){
            requestAnimationFrame(step);
        }
    })

抛物线

5.简谐摆动

 circle.on('click', function() { 
   
    var self = this;
    var startTime = Date.now();
    var distance = 100;
    var T = 2000;
    requestAnimationFrame(function step() { 
   
        var p = Math.min(1.0, (Date.now() - startTime) / T);
        var tx = distance * Math.sin(2 * Math.PI * p);
        self.style.transform = 'translateX(' + tx + 'px)';
        if(p < 1.0){
            requestAnimationFrame(step);
        }
    })
})

摆动

6.正弦线

circle.on('click', function() { 
   
    var self = this;
    var startTime = Date.now();
    var distance = 100;
    var T = 2000;
    requestAnimationFrame(function step() { 
   
        var p = Math.min(1.0, (Date.now() - startTime) / T);
        var ty = distance * Math.sin(2 * Math.PI * p);
        var tx = 2 * distance * p;
        self.style.transform = 'translate(' + tx + 'px,'+ ty +'px)';
        if(p < 1.0){
            requestAnimationFrame(step);
        }
    })
})

正弦

7.圆周运动

circle.on('click', function() { 
   
    var self = this;
    var startTime = Date.now();
    var distance = 100;
    var T = 2000;
    var r = 100;
    requestAnimationFrame(function step() { 
   
        var p = Math.min(1.0, (Date.now() - startTime) / T);
        var rotation = p * 360;
        self.style.transformOrigin = 'r' + 'px ' + r + 'px';
        self.style.transform = 'rotate(' + rotation +'deg)';
        if(p < 1.0){
            requestAnimationFrame(step);
        }
    })

圆周运动

动画封装

可以将动画封装成通用的对象,每次只需要实例定义单帧执行函数就可以了。

参数:duration-动画持续时间,progress每一帧执行的函数,easing-缓动效果(可传可不传)
function Animator(duration, progress, easing) { 
   
    this.duration = duration;
    this.progress = progress;
    this.easing = easing || function(p){ 
   return p};
}
//调用start函数时可传入参数,如果参数为false或者传入的函数返回false,那么就说明进行循环动画,相当于将css animation中的animation-iteration-count:infinite
Animator.prototype.start = function(finished) { 
   
    var self = this;
    var startTime = Date.now();
    var duration = self.duration;

    requestAnimationFrame(function step(){ 
   
        var p = (Date.now() - startTime) / duration;
        var next = true;
        if(p < 1.0) {
            self.progress(self.easing(p), p);
        }else { //第一次动画之行完后开始执行回调函数
            if(typeof finished === 'function') {
                next = finished() === false;
            }else {
                next = finished === false;
            }
          //如果调用start时传递的参数为false或函数返回false,next便为true说明进行循环运动
            if(!next) {
                self.progress(self.easing(1.0), 1.0);
            }else {
                startTime += duration;  //如果这里不加的话那么小球不会循环,而是一直向前运动
                self.progress(self.easing(p), p);
            }
        }
       //next为true,动画继续执行
        if(next) {
            requestAnimationFrame(step);
        }
    })
}

目前这个函数存在的缺点就是虽然可以设置动画执行为一次或一直循环,但是并不能设置动画执行次数为2,3,4..,也不能设置动画循环的方向,即不能像css animation设置animation-direction

  • 折线运动
    让小球先向右运动再向下运动
var a1 = new Animator(1000, function(p) { 
   
    var tx = 100 * p;
    circle.style.transform = 'translateX(' + tx + 'px)';     
})
var a2 = new Animator(1000, function(p) { 
   
    var ty = 100 * p;
    circle.style.transform = 'translate(100px,' + ty + 'px)';   
})
a1.start(function(){ 
   
   a2.start();
})

折线运动

动画队列

为了能使多个动画顺序执行,需要用数组来模拟一个队列管理动画执行顺序。

function AnimationQueue(animators) { 
   
    this.animators = animators || [];
}
AnimationQueue.prototype = {
    append: function() { 
   
        var args = [].slice.call(arguments);
        this.animators.push.apply(this.animators, args);
    },
    flush: function() { 
   
        if(this.animators.length) {
            var self = this;
            function play() { 
   
                var animator = self.animators.shift();
                        //如果数组中的对象是Animator的实例,则直接调用
                if(animator instanceof Animator) {
                    animator.start(function() { 
   
                    if(self.animators.length) {
                            play();
                        }
                    })
                }else { //数组中的对象不是Animator的实例,调用Animator的方法,可以在这里将之前的对象再次添加到animators数组中
                    animator.apply(self);//通过这里可以进行循环运动
                    if(self.animators.length) {
                        play();
                    }
                }
            }
            play();
        }
    }
}
  • 弹跳的小球
    • 设20px为1米,下落距离为200px, 为10米
    • g = 10m/s
    • S = 1/2 * g * T^2 = 10
    • T = 1.414s = 1414ms
    • 下落阶段 St = S * p^2
    • 上升阶段 St = S – Sp * (2 – p)
var c1 = new Animator(1000, function(p) { 
   
    var ty = 200 * p * p;
    circle.style.transform = 'translateY(' + ty + 'px)';
})
var c2 = new Animator(1414, function(p) { 
   
    var ty = 200 - 200 * p * (2 - p);
    circle.style.transform = 'translateY(' + ty + 'px)';
})
circle.addEventListener('click', function() { 
   
    var animators = new AnimationQueue();
    animators.append(c1, c2, function execute() { 
   
        this.append(c1,c2, execute);
    });
    animators.flush();
})

弹跳

  • 弹跳幅度逐渐减小的小球
    • 上升时间:T = 0.7 * T
    • 上升距离:S = 0.49 * S

circle.addEventListener('click', function() { 
   
    var T = 1414;
    var a1 = new Animator(T, function(p) { 
   
        var s = this.duration * 200 / T;
        var ty = s * (p * p - 1);
        circle.style.transform = 'translateY(' 
      + ty + 'px)';     
    })
    var a2 = new Animator(T, function(p) { 
   
        var s = this.duration * 200 / T;
        var ty = - s * p * (2 - p);
        circle.style.transform = 'translateY(' 
      + ty + 'px)'; 
    })
    var animators = new AnimationQueue();
    function foo() { 
   
        a2.duration *= 0.7;
        if(a2.duration <= 0.0001) {
            animators.animators.length = 0;
        }
    }
    animators.append(a1, foo, a2, function b() { 
   
        a1.duration *= 0.7;
        this.append(a1, foo, a2, b);
    });
    animators.flush();
})

弹跳幅度减小的小球

  • 滚动的小球
    • 小球直径:d = 50px
    • 圆周长: l = π * d;
    • 周期: T = 2s
    • 滚动时间: t = 4s
    • 滚动距离:S = π * d * t / T = 314px
circle3.addEventListener('click', function() { 
   
    var a1 = new Animator(4000, function(p) { 
   
        var rotation = 'rotate(' + 720 * p + 'deg)';
        var x = 50 + 314 * p + 'px';
        circle3.style.transform = rotation;
        circle3.style.left = x;
    });
    var animators = new AnimationQueue();
    animators.append(a1, function b() { 
   
        animators.append(a1, b);
    })
    animators.flush();
})

滚动的小球

以上就是利用我们学过的常见物理公式实现的js动画效果。当然还可以有更多复杂的效果,如何实现各种优美的动画也是值得深入学习的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/181724.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 树莓派4B基础教程

    树莓派4B基础教程树莓派4B基础教程准备:硬件:树莓派4B,SD一张软件:SDCardFormatter(SD卡格式化工具),Win32DiskImager(烧录系统工具)这是一个纯新手教程,由于更新换代,有些东西3b的教程能用4b用不了,由于版本原因,有些东西直接出错,所以干脆花时间自己整理了一下.作者自述:对!东西全是百度来的,劳资只是一个搞Java开发的,也没有见过这些小东西可能比普通…

    2022年6月10日
    54
  • window 启动tomcat闪退 查看日志方法

    window 启动tomcat闪退 查看日志方法window启动tomcat闪退查看日志方法找到bin下面的startup.bat用文本方式打开找到末尾start改为run然后打开cmd窗口cd到tomcatbin路径执行startup.bat下图本来该报错会闪退,catalina日志文件也没记录该报错,导致我们看不到报错信息,设置后可清晰看到报错原因,端口号超出范围,改小就行了…

    2022年5月29日
    61
  • python基础系列教程——Python的安装与测试:python解释器、PyDev编辑器、pycharm编译器

    python基础系列教程——Python的安装与测试:python解释器、PyDev编辑器、pycharm编译器全栈工程师开发手册(作者:陈玓玏)python教程全解白手起家,从头开启python的开发环境搭建。一.如何安装Python在https://www.python.org/下载安装包。下载下来一个exe文件,直接双击运行。选择InstallNow,立即安装。配置环境变量:右键开始——控制面板——系统——高级系统配置——环境变量。找…

    2022年7月23日
    13
  • 【Java】Red5服务器搭建(实现在线直播,流媒体视频播放)「建议收藏」

    引言流媒体文件是目前非常流行的网络媒体格式之一,这种文件允许用户一边下载一边播放,从而大大减少了用户等待播放的时间。另外通过网络播放流媒体文件时,文件本身不会在本地磁盘中存储,这样就节省了大量的磁盘空间开销。正是这些优点,使得流媒体文件被广泛应用于网络播放。流媒体服务器是通过建立发布点来发布流媒体内容和管理用户连接的。流媒体服务器能够发布从视频采集卡或摄像机等设备中传来的实况流,也可以发布事先…

    2022年4月18日
    300
  • cnpm 安装命令

    cnpm 安装命令  npm包管理器是每一位js开发者的得力助手,利用npm我们不仅能下载到别人写好的组件,也可以快速搭建我们的项目……但对于国内的开发者,npm的下载速度有是实在是令人捉鸡,因此国内的许多开发者都会使用更加快速的cnpm简单代替npm。打开控制台,输入命令npminstall-gcnpm–registry=https://registry.npm.taobao.org耐心等待一下安装即可此后我们再使用npm下载包的时候,就可以将npm命令替换为cnpm,下载下来的内容完全一样,但是速度

    2022年10月15日
    2
  • .net mysql transactionscope_C#中的事务TransactionScope

    .net mysql transactionscope_C#中的事务TransactionScopeTransactionOptionstransactionOption=newTransactionOptions();//设置事务隔离级别transactionOption.IsolationLevel=System.Transactions.IsolationLevel.Serializable;//设置事务超时时间为60秒transactionOption.Timeout=new…

    2022年7月19日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号