在 MDN web docs 中有过关于使用 canvas 来绘制太阳系动画的例子,此种方法需要使用 translate 来不断改变画布原点。
MDN 示例参考:太阳系运动示例
现在需要在 canvas 画布上绘制一个小球绕椭圆转动的动画效果
首先可以使用 js 构造函数模式定义一个小球对象 (只有当一个函数以 new 关键字来调用的时候,我们才能说它是一个构造函数)
function ball(x, y, obj) { this.x = x; this.y = y; this.angle = 0; this.draw = function() { var self = this; ctx.drawImage(obj, self.x, self.y); }};
复制代码
通过以下代码将小球绘制在画布上
<style type="text/css"> #mycanvas { margin: 80px; border: 1px solid black; }</style><canvas id="mycanvas" width="500" height="500"></canvas> <script type="text/javascript"> var canvas = document.getElementById('mycanvas'); var ctx = canvas.getContext('2d'); var imgball = new Image(); // 创建img元素 imgball.src = './img/Canvas_earth.png'; imgball.onload = function() { ctx.drawImage(imgball, 200, 100); }
function ball(x, y, obj) { this.x = x; this.y = y; this.angle = 0; this.draw = function() { var self = this; ctx.drawImage(obj, self.x, self.y); } }; var ball01 = new ball(167, 100, imgball); function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ball01.draw(); }</script>
复制代码
ctx.clearRect(0, 0, canvas.width, canvas.height);可以清除画布之前的轨迹
效果:
接下来可以让小球做正椭圆轨迹运动,小球的直径是 24,半径是 12。
使用 requestAnimationFrame 来让小球的运动变得较为流畅,当然也可以使用定时 setInterval 来进行操作
(requestAnimationFrame 是浏览器用于定时循环操作的一个接口,类似于 setTimeout。优势在于充分利用显示器的刷新机制,比较节省系统资源)
<script type="text/javascript"> var canvas = document.getElementById('mycanvas'); var ctx = canvas.getContext('2d'); var imgball = new Image(); // 创建img元素 imgball.src = './img/Canvas_earth.png'; imgball.onload = function() { ctx.drawImage(imgball, 200, 100); }
function ball(x, y, obj) { this.x = x; this.y = y; this.angle = 0; this.draw = function() { var self = this; ctx.drawImage(obj, self.x, self.y); } };
var ball01 = new ball(167, 100, imgball); var P0 = 0, P1 = 0, Z0 = 9 ,Z1 = 3; function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); if (ball01.angle == 360) { ball01.angle = 0; } ball01.angle += 1; //角度 var radian = ball01.angle * (Math.PI / 180); //弧度
ball01.x = (167 + 140 * Math.cos(radian)) - 24 / 2; //小球半径 ball01.y = (100 + 40 * Math.sin(radian)) - 24 / 2; ball01.draw(); raf = window.requestAnimationFrame(draw); } draw();</script>
复制代码
效果:
而斜椭圆则是相当于正椭圆相对于中心原点旋转一定角度后形成的
斜椭圆 x,y 坐标点的计算公式:
最终小球椭圆轨迹运行代码:
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <script src="js/vue.js" type="text/javascript" charset="utf-8"></script> <title></title> <style type="text/css"> #mycanvas { margin: 80px; border: 1px solid black; } </style> </head> <body> <canvas id="mycanvas" width="500" height="500"></canvas>
<script type="text/javascript"> var canvas = document.getElementById('mycanvas'); var ctx = canvas.getContext('2d'); var imgball = new Image(); // 创建img元素 imgball.src = './img/Canvas_earth.png';
function ball(x, y, obj) { this.x = x; this.y = y; this.angle = 0; this.draw = function() { var self = this; ctx.drawImage(obj, self.x, self.y); } };
var ball01 = new ball(167, 100, imgball); function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); if (ball01.angle == 360) { ball01.angle = 0; } ball01.angle += 1; //角度 var radian = ball01.angle * (Math.PI / 180); //弧度 var nx = (167 + 140 * Math.cos(radian)) - 24 / 2; var ny = (100 + 40 * Math.sin(radian)) - 24 / 2; ball01.x = nx * Math.cos(-1 / 6 * Math.PI) - ny * Math.sin(-1 / 6 * Math.PI) - 50; ball01.y = nx * Math.sin(-1 / 6 * Math.PI) + ny * Math.cos(-1 / 6 * Math.PI) + 80; ball01.draw();
raf = window.requestAnimationFrame(draw); } draw(); </script> </body></html>
复制代码
效果:
如果不进行轨迹消除,那么形成的椭圆就如下图所示:
评论