# 动画
实现一个动画也是比较简单的,就是不断擦除和重新绘制图形,并且在每次重新绘制的时候进行改变其角度就实现了动画。
我们还是用之前的三角形进行实现一个旋转三角形,在一定的时间去重新修改旋转角度,来实现动画效果。
在设置旋转之前,我们需要设置背景色,而不是在进行绘制之前设置背景色,记住在 webgl 中,设置好的背景色在重设之前一直有效。
实现旋转的关键代码如下:
// 旋转速度(度/秒)
var ANGLE_STEP = 45.0;
function main() {
// 设置顶点位置
var n = initVertexBuffers(gl);
// 设置 canvas 背景色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 获取 u_ModelMatrix 变量的存储位置
var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
// 三角形的当前旋转角度
var currentAngle = 0.0;
// 模型矩阵 Matrix4 对象
var modelMatrix = new Matrix4();
// 开始绘制三角形
var tick = function() {
// 更新旋转角
currentAngle = animate(currentAngle);
// gl 绘制三角形的上下文
// n 顶点个数
// currentAngle 当前的旋转角度
// modelMatrix 根据当前的旋转角度 currentAngle 计算出的旋转矩阵,存储在 matrix4 对象中
// u_ModelMatrix 顶点着色器中同名的 uniform 变量的存储位置,modelMatrix 变量江北传递至此处
draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix);
// 请求浏览器调用 trick
requestAnimationFrame(tick, canvas);
};
tick();
}
function initVertexBuffers(gl) {
var vertices = new Float32Array ([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
// 顶点的个数
var n = 3;
// 创建缓冲区对象等代码
return n;
}
function draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {
// 设置旋转矩阵 setRotate 是计算出一个旋转矩阵,绕着 z 轴
modelMatrix.setRotate(currentAngle, 0, 0, 1);
// 将旋转矩阵传输给顶点着色器
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
// 清除 canvas
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, n);
}
// 记录上一次调用函数的时间
var g_last = Date.now();
function animate(angle) {
// 计算距离上一次调用经过多长时间
var now = Date.now();
var elapsed = now - g_last;
g_last = now;
// 根据距离上次调用的时间,更新当前旋转角度
var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
return newAngle %= 360;
}
setRotate 是封装的一些方法,
# requestAnimationFrame 方法
在实现定时渲染的时候并没有没有 setInterval 函数,因为 setInterval 函数不管浏览器标签页是否被激活,他都会反复执行里面的代码。会增加浏览器的负荷。 而 settimeout 是通过设定间隔时间来不断改变图像位置,达到动画效果。但是容易出现卡顿、抖动的现象;原因是:1、settimeout任务被放入异步队列,只有当主线程任务执行完后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;2、settimeout的固定时间间隔不一定与屏幕刷新时间相同,会引起丢帧。 requestAnimation 方法只有当标签页处于激活状态的时候才会生效,requestAnimationFrame 是新引入的方法;他主要作用是请求浏览器在将来某时刻回调函数 func 以完成重绘,我们应道在回调函数最后再次发起该请求。优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。你无法指定重复调用的间隔,回调函数会在浏览器需要网页的某个元素(第二个参数)重绘时被调用,此外还需要注意,在浏览器成功地调用了一次回调函数后,想要再次调用它,就必须要再次发送请求,因为前一次请求已经结束。
如果想要取消其你去,需要使用 cancelAnimationFrame() 函数:
cancelAnimationFrame(requestId) 取消由 requestAnimationFrame() 发起的请求,参数 requestId 为指定 requestAnimationFrame() 的返回值;
评 论:
← webgl基础 webgl颜色与纹理 →