高中物理学运动公式实现js动画
在網(wǎng)頁上創(chuàng)建動畫一般有兩種方式:css和javascript。它們在創(chuàng)建動畫的時間和性能上是不一樣的,各有利弊。選擇哪種方法實際上取決于項目,以及想要實現(xiàn)什么類型的動畫。
一般使用css動畫來實現(xiàn)比較簡單的“一次性轉(zhuǎn)換”,為UI元素轉(zhuǎn)換比較小的獨立狀態(tài)。例如從側(cè)面引入導(dǎo)航欄菜單,模太框彈出等。
要實現(xiàn)高級效果時,例如彈跳,加速,減速等比較復(fù)雜的動畫,則使用Javascript動畫。現(xiàn)在有很多比較好的JS動畫框架,例如TweenMax,Velocity,animo.js,jquery。
不管是css還是javascript來創(chuàng)建動畫,我們都會聽到一個詞“緩動”。自然界中沒有東西從一點呈線性的移動到另一點,一般可能需要加速或減速。在經(jīng)典動畫中,經(jīng)常會出現(xiàn)“緩入”,“緩出”,“緩入緩出”效果。緩動使動畫不再那么尖銳或生硬。
css中,我們要想達到這些效果,只需要使用一些關(guān)鍵字:
* linear
* ease-in
* ease-out
* ease-in-out
那這么關(guān)鍵字的背后到底是什么原理呢?如何用javascript來實現(xiàn)這些緩動效果。
動畫是關(guān)于時間的函數(shù),本質(zhì)就是利用瀏覽器和GPU的渲染過程定時改變元素的屬性。
使用javascript實現(xiàn)動畫時一般是使用requestAnimationFrame,我們可能經(jīng)常也會用setInterval和setTimeout來實現(xiàn)動畫,但是它們實現(xiàn)的動畫都不會與屏幕的刷新率同步,并且很可能出現(xiàn)抖動和跳幀,例如jQuery就是采用setInterval來實現(xiàn)動畫,所以jQuery動畫的幀率會偏低(jQuery為甚么不采用RAF)。
“Talk is cheap, show me the code”。下面學(xué)習(xí)實現(xiàn)下月影總結(jié)的動畫原理。原理簡單,實現(xiàn)經(jīng)典。
常見運動
勻速運動
讓小球在2s內(nèi)向右勻速移動200px
- 時間: t = T * p
- 位移: St = S * p = v * t
- 速度: v = St / t = S / T
- 加速度: a = 0
2.勻加速運動
讓小球在2s內(nèi)向右勻加速向右移動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
3.勻減速運動
讓小球在2s內(nèi)向右勻減速向右移動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
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);}})動畫封裝
可以將動畫封裝成通用的對象,每次只需要實例定義單幀執(zhí)行函數(shù)就可以了。
參數(shù):duration-動畫持續(xù)時間,progress每一幀執(zhí)行的函數(shù),easing-緩動效果(可傳可不傳) function Animator(duration, progress, easing) {this.duration = duration;this.progress = progress;this.easing = easing || function(p){return p}; } //調(diào)用start函數(shù)時可傳入?yún)?shù),如果參數(shù)為false或者傳入的函數(shù)返回false,那么就說明進行循環(huán)動畫,相當于將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 { //第一次動畫之行完后開始執(zhí)行回調(diào)函數(shù)if(typeof finished === 'function') {next = finished() === false;}else {next = finished === false;}//如果調(diào)用start時傳遞的參數(shù)為false或函數(shù)返回false,next便為true說明進行循環(huán)運動if(!next) {self.progress(self.easing(1.0), 1.0);}else {startTime += duration; //如果這里不加的話那么小球不會循環(huán),而是一直向前運動self.progress(self.easing(p), p);}}//next為true,動畫繼續(xù)執(zhí)行if(next) {requestAnimationFrame(step);}}) }目前這個函數(shù)存在的缺點就是雖然可以設(shè)置動畫執(zhí)行為一次或一直循環(huán),但是并不能設(shè)置動畫執(zhí)行次數(shù)為2,3,4..,也不能設(shè)置動畫循環(huán)的方向,即不能像css animation設(shè)置animation-direction
- 折線運動
讓小球先向右運動再向下運動
動畫隊列
為了能使多個動畫順序執(zhí)行,需要用數(shù)組來模擬一個隊列管理動畫執(zhí)行順序。
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();//如果數(shù)組中的對象是Animator的實例,則直接調(diào)用if(animator instanceof Animator) {animator.start(function() {if(self.animators.length) {play();}})}else { //數(shù)組中的對象不是Animator的實例,調(diào)用Animator的方法,可以在這里將之前的對象再次添加到animators數(shù)組中animator.apply(self);//通過這里可以進行循環(huán)運動if(self.animators.length) {play();}}}play();}} }- 彈跳的小球
- 設(shè)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)
- 彈跳幅度逐漸減小的小球
- 上升時間:T = 0.7 * T
- 上升距離:S = 0.49 * S
- 滾動的小球
- 小球直徑:d = 50px
- 圓周長: l = π * d;
- 周期: T = 2s
- 滾動時間: t = 4s
- 滾動距離:S = π * d * t / T = 314px
以上就是利用我們學(xué)過的常見物理公式實現(xiàn)的js動畫效果。當然還可以有更多復(fù)雜的效果,如何實現(xiàn)各種優(yōu)美的動畫也是值得深入學(xué)習(xí)的。
總結(jié)
以上是生活随笔為你收集整理的高中物理学运动公式实现js动画的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于微信小程序商店管理系统源码成品(微信
- 下一篇: hexo yilia主题添加音乐