在 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>
复制代码
效果:
如果不进行轨迹消除,那么形成的椭圆就如下图所示:
评论