赵工的个人空间


网络课堂部分转网页计算部分转编程演练

 制作有趣的网页

首页 > 网络课堂 > 制作有趣的网页 > canvas中动态画个圆
canvas中动态画个圆
HTML5规范中增加了canvas标记,可以在上面画图,还可以画出动图。所谓动图,其实就是多帧图像或多幅图像,每帧之间有稍许差别,以固定间隔显示,连续看起来就如同在运动,无论电影还是电视,都是依据这种方法实现的。
最初,在浏览器中实现固定间隔的显示,是使用window.setTimeout() 或 window.setInterval()方法来实现的,通过设置固定的一个时间间隔参数,来实现定时的显示。不过,后来出现了window.requestAnimationFrame()和cancelAnimationFrame()方法,不再人工设置固定时间间隔数值,而是让浏览器根据实际自动选择一个间隔,这样实现的动画效果更好。window.requestAnimationFrame()的使用方法一般是这样一种架构:
var step=0, end=endvalue;
(function drawFrame() {
  ani=window.requestAnimationFrame(drawFrame);
  .........
  step+=1;
  if(step>end) cancelAnimationFrame(ani);
}());
其中定义了一个drawFrame()函数,也就是绘制动画的函数,而在其中使用了浏览器内置的自适应间隔调用方法window.requestAnimationFrame(drawFrame),并将自定义的这个绘制函数drawFrame作为其回调参数。这个自定义函数drawFrame使用括号()整个括起来,这样就是定义并运行这个函数,因此形成这样一种结构。为了使这个函数调用结构可以正常运行,一般需要预先定义一个变量step,当然使用其他名称也是可以的,而在drawFrame函数体中则使用递增方法不断更改这个变量,绘制图形时则通过这个变量的值的改变来控制图形的变化。一般还会设置一个结束值,这里为end,应为一个固定数值大小,这里以endvalue替代,使用时比较容易更改,达到这个值时使用cancelAnimationFrame()来取消这个固定间隔的调用,因为这个方法需要使用一个标识id,指明要取消的是哪个回调方法,因此在使用window.requestAnimationFrame()时需要把这个id先赋值给一个变量ani,存储起来,便于以后的取消。
有些人不喜欢这种比较难以理解的结构,而喜欢使用另一种方式:
var step=0, end=endvalue;
function drawFrame() {
  ani=window.requestAnimationFrame(drawFrame);
  .........
  step+=1;
  if(step>end) cancelAnimationFrame(ani);
}
window.requestAnimationFrame(drawFrame);
先定义一个drawFrame()函数,然后再使用window.requestAnimationFrame(drawFrame)来调用,其实功能是一样的。使用requestAnimationFrame做动画时,一般这个架构并不需要改变,直接套用就可以,只是要根据自己的需要加入绘制的内容。
这里使用最简单的画线方法画一个圆。为了画出一个圆,需要逐个计算出圆弧上的每个点,一个圆是从0到360度,为了比较圆滑,按每一度一个点计算,step就作为每个角度的值,不断增加,从0到360。按解析几何,圆的方程可以表示为x=cos(step),y=sin(step),不过这是圆的原点在(0,0)时的情况,而在canvas中绘图,左上角为(0,0),中心点为(canvas.width/2,canvas.height/2),圆上的任何一点的x坐标和y坐标都需要加上这个中心点的坐标,也就是cos(step) +canvas.width/2和sin(step)+canvas.height/2,当然也可以使用translate() 的坐标移动方法。
这样,drawFrame()函数中代码就为:
context.moveTo(r+centerX,centerY);
context.beginPath();
(function drawFrame() {
  ani=window.requestAnimationFrame(drawFrame);
  x=r*Math.cos(step*Math.PI/180);
  y=r*Math.sin(step*Math.PI/180);
  context.lineTo(x+centerX,y+centerY);
  context.stroke();
  step+=1;
  if(step>361) cancelAnimationFrame(ani);
}());
其中context.lineTo()方法是在canvas中画线的,用于将计算出的每个点连接而形成一个圆弧。因为JavaScript中的三角函数是使用弧度,所以代码中要将角度值step转换为弧度值,然后再计算。而结束值设为361,是避免最后绘出的曲线有个缺口。
完整的网页代码为:
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="gb18030" />
  <title>画圆</title>
</head>
<body>
<canvas id="canvas" width="600" height="600"> 你使用的浏览器不支持需要的功能,请升级或更换!</canvas>
<script type="text/javascript">
let canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
window.onload=function(){
  let centerX=canvas.width/2,
    centerY=canvas.height/2,
    step=1,
    r=0.9*centerY,
    ani,x,y;
  context.lineWidth=2;
  context.moveTo(r+centerX,centerY);
  context.beginPath();
  (function drawFrame() {
    ani=window.requestAnimationFrame(drawFrame);
    x=r*Math.cos(step*Math.PI/180);
    y=r*Math.sin(step*Math.PI/180);
    context.lineTo(x+centerX,y+centerY);
    context.stroke();
    step+=1;
    if(step>361) cancelAnimationFrame(ani);
  }());
};
</script>
</body>
</html>
因为此网页文件没有引入外部文件,所以可以直接存储为html文件,放置在一个任意位置,比如桌面,双击之后就可以运行。不过还是建议存储在固定的一个磁盘文件夹中,一般是在计算机中建立一个虚拟的网页服务器,把html都放入其中。打开此演示文件,显示的是一个从右端开始的逐点画圆的过程,画圆结束就停止。当然,有些动画是需要一直运行下去的,这时就不需要使用cancelAnimationFrame()方法,而是step到一个值就从0开始,循环往复,一直运行,直到关闭网页。
Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659