您的位置:首页 > Web前端 > JavaScript

canvas分享之三角函数(2)

2016-08-25 18:49 369 查看
在上一节我们介绍了canvas动画中有关三角函数的内容,以及一个跟随鼠标旋转的箭头动画。那么,在这一节呢!介绍的内容比较多,包括:

波形运动

圆周运动

两点间的距离


一.波形运动

sin函数的波形想必骚年们不会感到陌生,如果只是考虑一个周期以内的函数波形,如下图所示:



如果我们想要取到sin函数在[0, 2π]之间的值,非连续的情况下,可以这样估算:
for(var angle=0; angle<Math.PI*2; angle+=0.1){
console.log(Math.sin(angle)); //打印出角度对应的sin值
}


那么,它能做什么呢?别急,这里我们首先新建一个类,文件名为
ball.js
,顾名思义这是一个球体,我们将要通过它来表现不同的运动形态。这样,包括上一节中的箭头文件
arrow.js
,在你的js文件中就有两个类文件了:

js

arrow.js

ball.js

ball.js代码具体如下,这里就不做过多解释了。我们只是画了一个圆。
ball.js文件

function Ball(radius,color){
if(radius === undefined) {radius = 40;}
if(color === undefined){color = '#00ff00';}
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.radius = radius;
this.rotation = 0;
this.mass = 1;
this.scaleX = 1;
this.scaleY = 1;
this.color = utils.parseColor(color);
this.lineWidth = 1;

}

Ball.prototype.draw = function(context){
context.save();
context.translate(this.x,this.y);
context.rotate(this.rotation);
context.scale(this.scaleX,this.scaleY);
context.lineWidth = this.lineWidth;
context.fillStyle = this.color;
context.strokeStyle = this.color;
context.beginPath();
context.arc(0,0,this.radius,0,Math.PI*2,false);
context.closePath();
context.fill();
context.stroke();
context.restore();
}


1.平滑运动(Smooth motion)

这里我们首先介绍Math.sin(angle)的第一个应用——平滑运动。平滑(smoothly)这个词的意思是指物体的一种流畅的运动状态,与之相反的是机械式的简单的从0到1再到-1和0的这么一种状态。平滑的运动更加趋近与自然的运动状态,类似水草在水流中的左右摇摆,在摆动的过程中是有速度的变化的。我们用sin函数模仿的第一个运动,就是这种类似水草摆动的运动。另外,因为sin函数的值是在[-1,1]之间。所以在实际代码中需要乘以一个较大的值(也就是振幅,你懂得),使其摆动的幅度看起来明显一些。具体代码如下:
<canvas id="canvas" width="500" height="500" style="background:#000009;">
your browser not support canvas!
</canvas>
<script src="../js/utils.js"></script>
<script src="../js/ball.js"></script>
<script>
window.onload = function(){
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var ball = new Ball();
ball.x = canvas.width/2;
ball.y = canvas.height/2;

var angle = 0,
range = 50; //振幅

(function drawFram(){
window.requestAnimationFrame(drawFram,canvas);
context.clearRect(0,0,canvas.width,canvas.height);

ball.x = canvas.width/2 + Math.sin(angle)*range; //核心
angle += 0.1;

ball.draw(context);
})();
}
</script>


这样你就可以看到一个在canvas画布中心左右摇摆的球,相比于机械的加减是不是更加的流畅呢?当然,你也可以控制摆动的速度,怎么做呢?很简单
angle
+= speed
,将speed设置为任意大小的值就可以了。当然,如果你想让它做垂直运动只需要变化 ball.y 即可。


2.线性运动(Linear motion)

线性运动是最简单的一种运动,物体匀速朝某个方向运动,就是线性运动。这里直接给你具体代码:
<canvas id="canvas" width="500" height="500" style="background:#000;">
you browser not support canvas!
</canvas>
<script src="../js/utils.js"></script>
<script src="../js/ball.js"></script>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
var angle = 0,
range = 50,
xspeed = 1,
yspeed = 0.05;

var ball = new Ball();

(function drawFrame(){
window.requestAnimationFrame(drawFrame,canvas);
context.clearRect(0,0,canvas.width,canvas.height);

ball.x += xspeed; //水平,沿x轴方向水平运动

if(ball.x > canvas.width + ball.radius){
ball.x = -ball.radius;
}
//垂直, 由于angle角度没发生变化,所以纵坐标保持不变
ball.y = canvas.height/2+Math.sin(angle)*range;

// angle += 0.05; //取消注释看看发生了什么?
ball.draw(context);
})();
}
</script>


其实,这里如果你把
angle += 0.05
取消注释,你会发现球的运动轨迹就与sin函数的图像一致了。


3.脉冲运动(Pulsing motion)

脉冲运动是将sin函数运用于物体大小的变化中,即scale属性。具体代码如下:
window.onload = function(){
var canvas = document.getElementById('canvas');
var context  = canvas.getContext('2d');

var angle = 0,
range = 0.5,
speed = 0.05,
centerScale = 1;

var ball = new Ball();
ball.x = canvas.width/2;
ball.y = canvas.height/2;

(function drawFrame(){
window.requestAnimationFrame(drawFrame,canvas);
context.clearRect(0,0,canvas.width,canvas.height);

//sin值的变化,导致 ball.scaleX , ball.scaleY属性变化
ball.scaleX = ball.scaleY = centerScale + Math.sin(angle)*range;
angle += speed;

ball.draw(context);
})();
}


由此你应该知道,除了位置属性,我们还可以将sin函数与其他的属性相结合,来形成不同的运动形式。

在上面的代码中,我们几乎都是在球体的某一个属性上做出变动。当然,你也可以试一试同时在ball.x 和ball.y上运用sin函数,看看又能得到什么样的结果!sin函数的使用方法已经交给你了,到底能创造出什么样意想不到的作品就看你的了。


二、圆周运动

圆周运动可以分为两种形式:
正圆运动
椭圆运动


在讲圆周运动之前,各位骚年们,一大波数学公式正在向我们袭来。请护好自己的膝盖,听不懂没关系,只要记住程序怎么写就好了,能懂最好,这对后面学习高级动画是很有帮助的。好吧,那我就废话少说直接上菜了:




1.正圆运动

上图展示了从圆的
函数表达式
圆的极坐标表达式
之间的转换过程。理解不理解都没有关系,总之你要明白,最终我们将
x, y 与 sin 和 cos 扯上关系了。而圆的极坐标表达式就表示的是一个圆。这样我们想要让一个物体做圆周运动,那不就so easy了吗?具体代码如下:
window.onload = function(){
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');

var ball = new Ball();

var angle = 0, // 旋转的角度
centerX = canvas.width/2,
centerY = canvas.height/2,
radius = 100, // 定义半径
speed =0.05; // 每帧旋转角度的增加值

(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0,0,canvas.width, canvas.height);

//centerX, centerY 的作用是让球绕画布中心旋转
ball.x = centerX + Math.sin(angle)*radius;
ball.y = centerY + Math.cos(angle)*radius;

//角度增加
angle += speed;
ball.draw(context);
}());
}


ok,自己动手试试吧!看看是不是球体绕着画布中心做着圆周运动呢!这里我们需要的条件比较多, 包括了角度(angle) 和 半径(R)。在后面的章节中我们将介绍如何只通过 角度(angle) 就实现圆周运动。为了更容易理解,我劝你最好复习一下中学的知识,哈哈!!!


2.椭圆运动

椭圆和正圆的不同之处可以这样理解:正圆半径在x轴和y轴上的距离是相同的,即Radius。而椭圆则是不同的,我们用a, b 表示。



上图推到的过程也是告诉你如何通过,椭圆的函数表达式推导出其极坐标表达式。在极坐标表达式中我们再次找到了位置与角度,还有a,b的关系。具体到代码里,就是半径不同了呗!是不是so easy,上代码:
window.onload = function(){
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var ball = new Ball();

var centerX = canvas.width/2,
centerY = canvas.height/2,
angle = 0,
radiusX = 50,
radiusY = 100,
speed = 0.05;

ball.x = centerX;
ball.y = centerY;

(function drawFrame(){
window.requestAnimationFrame(drawFrame,canvas);
context.clearRect(0,0,canvas.width,canvas.height);

//当radius的值相等时为圆周运动
//当radius的值不想等是为椭圆运动
ball.x = centerX + Math.sin(angle)*radiusX; //radiusX = 50
ball.y = centerY + Math.cos(angle)*radiusY; //radiusY = 100
angle += speed;

ball.draw(context);
})();
}


三、两点之间的距离

按理来说,两点之间的距离是不会用到三角函数的。但是,其实两点间的距离公式是通过勾股定理推出来的,所以这里直接就把他归到三角函数里。

这里就不画示意图了直接给你个公式好了(原谅我偷个懒),假设有两个点, a(x1, y1), b(x2, y2)。那么怎样求它们之间的距离呢!公式如下:
dx = x2 - x1;
dy = y2 - y1;
distance = Math.sqrt(dx*dx + dy*dy); //这不就是勾股定理


这里给你个小的Demo,这个demo展示的是鼠标距离中心方块的距离,代码如下:
<canvas id="canvas" width="500" height="500" style="background:#000;">
your browser not support canvas!
</canvas>
<p id="log"></p>
<script src="../js/utils.js"></script>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
var log = document.getElementById('log');
var mouse = utils.captureMouse(canvas);
var context = canvas.getContext('2d');

//中心位置创建一个方块
var rect = {
x:canvas.width/2,
y:canvas.height/2
};

(function drawFrame(){
window.requestAnimationFrame(drawFrame,canvas);
context.clearRect(0,0,canvas.width,canvas.height);

var dx = mouse.x - rect.x;
var dy = mouse.y - rect.y;
var dis = Math.sqrt(dx*dx + dy*dy);

//画方块
context.fillStyle = '#ffffff';
context.fillRect(rect.x-2,rect.y-2,4,4);
//画线
context.save();
context.strokeStyle = '#ffffff';
context.beginPath()
context.moveTo(rect.x,rect.y);
context.lineTo(mouse.x,mouse.y);
context.closePath();
context.stroke();
context.restore();
//显示距离
log.style.left = (mouse.x + rect.x)/2 + 'px';
log.style.top = (mouse.y + rect.y)/2 + 'px';
log.innerHTML = dis;
})();
}
</script>


四、总结

哈哈,来给本章的重要公式做一个总结,我真是好人呐:

## 角度旋转
dx = mouse.x - object.x;
dy = mouse.y - object.y;
object.rotation = Math.atan2(dy,dx)*180/Math.PI

## 平滑运动
value = center + Math.sin(angle)*range;
angle += speed;

## 正圆运动
x_position = centerX + Math.sin(angle)*radius;
y_position = centerY + Math.cos(angle)*radius;
angle += speed;

## 椭圆运动
x_position = centerX + Math.cos(angle)*radiusX;
y_position = centerY + Math.sin(angle)*radiusY;
angle += speed;

##两点间距离
dx = x2 - x1;
dy = y2 - y1;
dist = Math.sqrt(dx*dx + dy*dy);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息