06-ArcGIS For JavaScript-requestAnimationFrame动画渲染

文章目录

概述

本节主要讲解与时间相关的三个方法setTimeout()、setInterval()和requestAnimationFrame(),这三个方法都属于浏览器的window对象的方法,这三个函数能够更好的服务于2Dcanvas动画、WebGL动画等方面。

setInterval()与setTimeout()

setInterval()函数为周期定时器,可以选择每过一个固定时间段调用一次指定函数。如下,每100毫秒调用一次回调函数:

javascript 复制代码
setInterval(function(){
	console.log("It is setInterval");
}, 100);

setTimeout()为倒计时定时器,例如可以指定100毫秒后调用回调函数,然后结束当前定时。

javascript 复制代码
setTimeout(function(){
	console.log("It is setTimeout");
}, 100);

这两个方法都是可以人为的指定回调函数被调用的时间。

如果不想使用该定时器的时候,可以选择取消。方法如下:

javascript 复制代码
clearInterval();  //取消setInterval()设置的定时
clearTimeout();  //取消setTimeout()设置的定时器

requestAnimationFrame()

requestAnimationFrame主要用途是按帧对网页进行重绘,让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

调用方式如下:

javascript 复制代码
function callback(){
	console.log(requestAnimationFrame)
	requestAnimationFrame(callback)
}
requestAnimationFrame(callback)

requestAnimationFrame在ArcGIS For JavaScript的应用

javascript 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" />
   <script src="https://js.arcgis.com/4.30/"></script>

   <style>
       html,
       body,
       #viewDiv {
           margin: 0;
           padding: 0;
           height: 100%;
           width: 100%;
       }
   </style>

   <script>
       require([
           "esri/geometry/Mesh",
           "esri/views/SceneView",
           "esri/Map",
           "esri/Graphic",
           "esri/symbols/MeshSymbol3D",
           "esri/symbols/FillSymbol3DLayer",
           "esri/geometry/Point",
           "esri/core/reactiveUtils"
       ], (Mesh, SceneView, Map, Graphic, MeshSymbol3D, FillSymbol3DLayer, Point, reactiveUtils) => {
           let waterHeight = 422;
           async function createMeshGLTF(glbUrl, point, i = [0, 0, 0], r = 1, n = 0) {

               const s = await Mesh.createFromGLTF(point, glbUrl, {
                   vertexSpace: "georeferenced"
               }), o = i.map(h => h * r);

               return s.scale(r),
                   s.offset(o[0], o[1], o[2]),
                   s.rotate(0, 0, n),
                   new Graphic({
                       geometry: s,
                       symbol: new MeshSymbol3D({
                           symbolLayers: [new FillSymbol3DLayer]
                       })
                   })
           }

           let map = new Map({
               basemap: 'satellite'
           })

           let view = new SceneView({
               container: "viewDiv",
               map
           })

           let animatingPinpoint = true;

           view.when(async function () {

               let sailBoat = await createMeshGLTF("./pinpoint.glb", new Point({
                   x: -1354454634895185e-8,
                   y: 4307521548889681e-9,
                   z: waterHeight,
                   spatialReference: {
                       wkid: 102100
                   }

               }));
               view.graphics.add(sailBoat);
               view.extent = sailBoat.geometry.extent;

               function setupCameraHeadingListener() {
                   reactiveUtils.watch(() => Math.round(view.camera.heading), e => {
                       const i = sailBoat.geometry;
                       i.transform.rotationAngle = -e + 20,
                           i.transform.rotationAxis = [0, 0, 1]
                   }
                       , {
                           initial: !0
                       })
               }

               let startTime = Date.now() / 1000;

               function animatePinpoint(graphic) {
                   let startTime = null;
                   animatingPinpoint = true;
                   const animate = (elapsedTime) => {
                       if (!startTime) {
                           startTime = elapsedTime;
                       }
                       const timeDif = (elapsedTime - startTime) / 1000;
                       const scale = 1 + Math.abs(Math.sin(timeDif * 2));
                       const geometry = graphic.geometry;
                       geometry.transform ??= new MeshTransform();
                       geometry.transform.scale = [scale, scale, scale];
                       if (animatingPinpoint) {
                           requestAnimationFrame(animate);
                       }
                   }
                   requestAnimationFrame(animate);
               }

               function stopAnimatingPinpoint() {
                   animatingPinpoint = false;
               }

               animatePinpoint(sailBoat);
               setupCameraHeadingListener();
           })
       })
   </script>
</head>

<body>
   <div id="viewDiv"></div>
</body>

</html>

结果

相关推荐
风逸hhh18 分钟前
python打卡day25@浙大疏锦行
开发语言·python
刚入门的大一新生22 分钟前
C++初阶-string类的模拟实现与改进
开发语言·c++
chxii2 小时前
5java集合框架
java·开发语言
老衲有点帅2 小时前
C#多线程Thread
开发语言·c#
C++ 老炮儿的技术栈2 小时前
什么是函数重载?为什么 C 不支持函数重载,而 C++能支持函数重载?
c语言·开发语言·c++·qt·算法
IsPrisoner2 小时前
Go语言安装proto并且使用gRPC服务(2025最新WINDOWS系统)
开发语言·后端·golang
&白帝&2 小时前
vue右键显示菜单
前端·javascript·vue.js
Wannaer2 小时前
从 Vue3 回望 Vue2:事件总线的前世今生
前端·javascript·vue.js
Python私教2 小时前
征服Rust:从零到独立开发的实战进阶
服务器·开发语言·rust