1.动画的实现原理就是不停的对canvas进行重绘
2.resquestAnimationFrame(func):请求浏览器在未来某个时刻回调函数func以完成重绘
function tick()
{
//绘图操作
requestAnimationFrame(tick);
}
setInterval()方法可以实现在指定时间间隔调用某方法,但是现代浏览器每个标签页具有独立的JavaScript环境,非激活状态下setInterval()方法仍然会运行,增加浏览器负荷
3.实现三角形匀速自动旋转:
var SHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'uniform mat4 u_xformMatrix;\n'+
'void main(){\n'+
'gl_Position = u_xformMatrix * a_Position;\n'+
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n'+
'uniform vec4 u_FragColor;\n'+
'void main(){\n'+
'gl_FragColor = u_FragColor;\n'+
'}\n';
//旋转速度(度/秒)
var ANGLE_STEP = 45.0;
function main()
{
var canvas = document.getElementById("webgl");
if(!canvas)
{
console.log("获取canvas标签失败");
}
var gl = canvas.getContext("webgl");
if(!gl)
{
console.log("获取上下文失败");
}
//设置背景色
gl.clearColor(0.0,0.4,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
if(!initShaders(gl,SHADER_SOURCE,FSHADER_SOURCE))
{
console.log("加载着色器程序失败");
}
var n = initVertexBuffers(gl);
if(n<0)
{
console.log("设置顶点失败");
}
//对片元着色器进行赋值
var u_FragColor = gl.getUniformLocation(gl.program,'u_FragColor');
gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0);
//模型矩阵
var modelMatrix = new Matrix4();
var u_xformMatrix = gl.getUniformLocation(gl.program,'u_xformMatrix');
var currentAngle = 0.0;
var tick = function()
{
currentAngle = animate(currentAngle);
draw(gl,n,currentAngle,modelMatrix,u_xformMatrix);
requestAnimationFrame(tick);
};
tick();
}
function initVertexBuffers(gl)
{
var vertices = new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5]);
var n = 3; //顶点个数
//创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if(!vertexBuffer)
{
console.log("创建缓冲区失败");
return -1;
}
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
//连接a_Position变量与分配给他的缓冲区对象
gl.enableVertexAttribArray(a_Position);
return 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;
}
function draw(gl,n,currentAngle,modelMatrix,u_xformMatrix)
{
modelMatrix.setRotate(currentAngle,0,0,1);
gl.uniformMatrix4fv(u_xformMatrix,false,modelMatrix.elements);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,n);
}
注意:(1)为了让三角形匀速旋转,不能直接在currentAnge上增加一个固定值,因为每次完成渲染一帧画面的时间不同。详见方法animate
(2)反复调用绘制函数机制