Table Of Content

动画原理

js中动画实现原理setInterval

js中动画实现新方法requestAnimationFrame

一个示例


动画原理

动画的本质实际上就是快速地不断变化的图片,每张图片对比前后两张图片有细微的变化。整个连续的过程达到一定速度在我们人眼看来就是动画。人眼一般能区分的帧率是24帧。过低给人的感觉就会很不流畅。

和我们小时候看的动画书原理一样

![](https://img2018.cnblogs.com/blog/1735896/202001/1735896-20200101155537787-253121630.gif)


### js中动画实现原理
在js中,要实现动画,我们首先需要做的第一件事情,就是找到一个能够以特定时间间隔的方法重复渲染画面,在Three.js中就是重绘场景Scene。在HMTL5之前,JavaScript中的做法是使用JS API提供的定时器,`setInterval(function,interval)`方法,通过该方法,我们可以指定一个定时器,让他间隔的调用定时器函数,例如每隔100毫秒调用一次,在定时器的回调函数中,定义场景渲染。
但是通过`setInterval`方法,有一些很致命的问题,那就是该定时器函数并不会考虑浏览器发生的动作,例如,打开一个新的页面,该方法在后台还是会不断的执行。此外,`setInterval`函数并不是和重绘屏幕同步进行,这将会导致很高的CPU占用,性能会很差。


### js中动画实现新方法
为了解决上述问题,现代浏览器提供了一个解决方案,那就是`requestAnimationFrame`方法。 通过该方法,你可以通过调用浏览器定义的方法,指定一个定时器。你的任何重绘都将在该提供的方法中进行。浏览器将会确保流畅高效地绘制场景,该方法的使用也非常简单,你只需要创建一个处理渲染的函数。如下示例:
```javascript
function renderScene(){
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
```
在该函数中,我们不断的调用本身,不断的重绘场景,实现动画效果。


### 一个示例:
以下是一个动画示例:
![](https://img2018.cnblogs.com/blog/1735896/202001/1735896-20200101223727644-1132905605.gif)

模型部分代码如下

function draw(scene,clock) {
var textureLoader = new THREE.TextureLoader();
//太阳
var sun = new THREE.SphereGeometry(50,50,50);
var sunMaterial = new THREE.MeshPhongMaterial({
map:textureLoader.load('./assets/2k_sun.jpg'),
color:0xffaaaa,
// wireframe:true
});
var sunModel = new THREE.Mesh(sun,sunMaterial); sunModel.position.set(0,60,0)
sunModel.castShadow = true;
//这个函数 每帧都会在渲染之前执行一次 所有的网格模型 都有这个方法
sunModel.onBeforeRender = function (renderer, scene, camera) {
var elapsed = clock.getElapsedTime();
this.rotation.y += -Math.PI/120 } scene.add(sunModel) //地球
var sphereGeometry = new THREE.SphereGeometry(20,40,50);
var sphereMaterial = new THREE.MeshPhongMaterial({
map:textureLoader.load('./assets/earth_atmos_2048.jpg'),
specular:0x333333,
});
var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
// sphere.position.y = 60
sphere.castShadow = true; //这个函数 每帧都会在渲染之前执行一次 所有的网格模型 都有这个方法
sphere.onBeforeRender = function (renderer, scene, camera) {
var elapsed = clock.getElapsedTime();
this.position.set(Math.sin(elapsed)*200,60,Math.cos(elapsed)*200);
this.rotation.y += -Math.PI/120 } scene.add(sphere) //月球
var moonGeometry = new THREE.SphereGeometry(5,40,50);
var moonMaterial = new THREE.MeshPhongMaterial({
map:textureLoader.load('./assets/moon_1024.jpg'),
specular:0x333333, });
var moon = new THREE.Mesh(moonGeometry,moonMaterial);
// sphere.position.y = 60
moon.castShadow = true; //这个函数 每帧都会在渲染之前执行一次 所有的网格模型 都有这个方法
moon.onBeforeRender = function (renderer, scene, camera) {
var elapsed = clock.getElapsedTime();
this.position.set((Math.sin(elapsed*5)*50+Math.sin(elapsed)*200),60,(Math.cos(elapsed)*200+Math.cos(elapsed*5)*50))
} scene.add(moon) }

控制更新以及初始化如下

function init() {
var stats = initStats();
var renderer = initRenderer();
var camera = initCamera();
var scene = new THREE.Scene();
var clock = new THREE.Clock();
// var elapsed = Math.acos(clock.getDelta()) initDefaultLighting(scene);
initModel()
initControls();
render();
draw(scene,clock); function initModel() {
//辅助工具
var helper = new THREE.AxesHelper(900);
scene.add(helper);
// var map = new THREE.TextureLoader().load("./assets/jay.jag");
//外部盒子
// var material = new THREE.MeshLambertMaterial({
// // map: map
// color: 0xffffff,
// });
// material.transparent = true;
// material.opacity = 0.4; //--------------------------------地板--------------------------
var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 50, 50);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
});
planeMaterial.transparent = true;
planeMaterial.opacity = 0.2; plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = -6;
plane.position.z = 0; //告诉底部平面需要接收阴影
plane.receiveShadow = true; scene.add(plane);
// scene.add(PlaneSegs);
//--------------------------------地板end-----------------------
} //初始化控制器
var obtControls; //定义控制器变量
function initControls() {
//定义控制器核心
obtControls = new THREE.OrbitControls(camera, renderer.domElement); // 如果使用animate方法时,将此函数删除
// controls.addEventListener('change', render);
//以下都是为了满足各种需求的各种控制器配置参数
obtControls.enableDampling = true; //使动画循环使用时阻尼或自转 意思是否有惯性
obtControls.enableZoom = true; //是否允许缩放
obtControls.enablePan = true; //是否开启鼠标右键拖拽
obtControls.autoRotate = false; //是否允许自动旋转
obtControls.dampingFactor = 0.25; //动态阻尼系数:就是鼠标拖拽旋转灵敏度
obtControls.minDistance = 0; //设置相机距离原点的最近距离;
obtControls.maxDistance = 1000; //设置相机距离原点的最远距离; }
//控制更新
function render() {
stats.update();
// fpControls.update(clock.getDelta());
obtControls.update(clock.getDelta());
requestAnimationFrame(render);
renderer.render(scene, camera)
} }

该demo的完整代码在这里:Link

Three中的动画实现-[three.js]的更多相关文章

  1. Three.js中的动画实现02-[Three.js]-[Object3D属性.onAfterRender/.onBeforeRender]

    Table Of Content Object3D简介以及两个属性的介绍 一个示例 Object3D简介以及两个属性的介绍 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对三维空间 ...

  2. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  3. 在网页中添加动画,使用WOW.js来实现

    [来源] 页面在向下滚动的时候,有些元素会产生细小的动画效果.虽然动画比较小,但却能吸引你的注意 刚知道wow.js这个插件,之前写的类似滚动时页面效果都是自己用jQuery写的,现在有了插件,开发更 ...

  4. 报表开发工具中开放的部分图表js接口列表

    1.. 描述 报表开发工具FineReport 8.0版本中开放了部分图表js接口,在具体应用的过程中很多人都不知道这些接口到底有什么作用,该怎么应用,所以根据我自己的应用在下面归纳了这些新开放js接 ...

  5. tween.js是一款可生成平滑动画效果的js动画库。tween.js允许你以平滑的方式修改元素的属性值。它可以通过设置生成各种类似CSS3的动画效果。

    简要教程 tween.js是一款可生成平滑动画效果的js动画库.相关的动画库插件还有:snabbt.js 强大的jQuery动画库插件和Tweene-超级强大的jQuery动画代理插件. tween. ...

  6. 第五章 jQuery中的动画

    通过jQuery中的动画方法,能轻松地为网页添加精彩的视觉效果,给用户一种全新体验. 1.show()方法和hide()方法 该方法的功能与css()方法设置display属性效果相同. 给show( ...

  7. JavaScript 基础——使用js的三种方式,js中的变量,js中的输出语句,js中的运算符;js中的分支结构

    JavaScript 1.是什么:基于浏览器 基于(面向)对象 事件驱动 脚本语言 2.作用:表单验证,减轻服务器压力 添加野面动画效果 动态更改页面内容 Ajax网络请求 () 3.组成部分:ECM ...

  8. Vue 中的动画特效

    Vue 中的动画特效 CSS 实现标签显隐 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  9. 分享JQuery动画插件Velocity.js的六种列表加载特效

    分享JQuery动画插件Velocity.js的六种列表加载特效.在这款实例中给中六种不同的列表加载效果.分别为从上飞入.从右侧飞入.从左侧飞入.和渐显.一起看下效果图: 在线预览   源码下载 实现 ...

随机推荐

  1. angular -——组件样式修改不成功

    angular组件样式修改不成功! 自己定义的css可以成功 组件的不行 style在模板字符串里 直接没有 class 是显示的 但是样式不生效 加上面 即可,为什么?我也不太清楚.有知道答案的请回 ...

  2. 一起学习vue源码 - Object的变化侦测

    作者:小土豆biubiubiu 博客园:www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d 简书:h ...

  3. 教妹学Java:Spring 入门篇

    你好呀,我是沉默王二,一个和黄家驹一样身高,刘德华一样颜值的程序员(管你信不信呢).从两位偶像的年纪上,你就可以断定我的码龄至少在 10 年以上,但实话实说,我一直坚信自己只有 18 岁,因为我有一颗 ...

  4. 基于FPGA的三段式状态机

    状态机分类: 通常, 状态机的状态数量有限, 称为有限状态机(FSM) .由于状态机所有触发器的时钟由同一脉冲边沿触发, 故也称之为同步状态机. 根据状态机的输出信号是否与电路的输入有关分为 Meal ...

  5. django 引入静态文件(前端样式等)

    1.首先在主项目目录下settings.py文件中添加如下代码 2.然后在主项目目录,app项目同级目录下新建static文件夹并在文件夹中新建css文件夹,用于存放css文件,如下: 3.前端渲染时 ...

  6. 将root用户权限赋予普通用户

    将root用户权限赋予普通用户 普通用户想要拥有root用户的权限,必须修改/etc/sudoers文件 ,还必须使用visudo命令修改.一是因为这个命令能防止多个用户同时修改这个文件,二是能进行有 ...

  7. c++ 中的单例类模板的实现方法

    1.什么是单例模式 在架构设计时,某些类在整个系统生命周期中最多只能有一个对象存在 ( Single Instance ).如超市收银系统,其外观主要由显示器(1个).扫描枪(1个).收款箱(1个)组 ...

  8. 【Weiss】【第03章】练习3.25:数组模拟队列

    [练习3.25] 编写实现队列的例程,使用 a.链表 b.数组 Answer: 在这章一开头就已经写了个链表的队列例程了,所以实际上只要做b小题就可以. 数组模拟队列和链表的两点小不同是: ①.数组空 ...

  9. STM32时钟配置方法

    一.在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. ①HSI是高速内部时钟,RC振荡器,频率为8MHz. ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率 ...

  10. GO语言web框架Gin之完全指南(一)

    作为一款企业级生产力的web框架,gin的优势是显而易见的,高性能,轻量级,易用的api,以及众多的使用者,都为这个框架注入了可靠的因素.截止目前为止,github上面已经有了 35,994 star ...