写点什么

canvas 小球绕斜椭圆轨迹运动

用户头像
空城机
关注
发布于: 2021 年 04 月 14 日
canvas小球绕斜椭圆轨迹运动

在 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);  }};
复制代码


  • x 和 y 代表绘制小球在画布上的坐标

  • angle 代表小球绕中心点运动的角度值,最大为 360。在动画绘制过程中,当角度等于 360 时让角度置为 0。

  • obj 为需要绘制的小球


通过以下代码将小球绘制在画布上

<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>
复制代码


效果:


如果不进行轨迹消除,那么形成的椭圆就如下图所示:


发布于: 2021 年 04 月 14 日阅读数: 104
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
canvas小球绕斜椭圆轨迹运动