实现缓动的策略:
为运动确定一个比例系数,这是一个小于1且大于0的小数
确定目标点
计算出物体与目标点的距离- 计算速度,速度 = 距离 x 比例系数
用当前位置加上速度来计算新的位置
重复第三步到第五步,直到物体到达目标
程序实现:
首先确定一个比例系数,比如设置为0.05,用变量easing表示:
var easing = 0.05;
接着确定目标点,在这里我们使用canvas元素的中心点:
var targetX = canvas.width / 2,
targetY = canvas.height / 2;
然后计算物体到目标点的距离。假设这个物体是一个小球,我们用ball来表示,小球的位置坐标为(x, y),目标点减去小球所在位置得到距离:
var dx = targetX - ball.x,
dy = targetY - ball.y;
速度就是距离乘以系数:
var vx = dx * easing,
vy = dy * easing;
ball.x += vx;
ball.y += vy;
完整代码如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Easing</title>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script src="js/ball.js"></script>
<script>
window.onload = function () {
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
ball = new Ball(),
easing = 0.05, // 比例系数
targetX = canvas.width / 2,
targetY = canvas.height / 2;
(function drawFrame () {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
var vx = (targetX - ball.x) * easing,
vy = (targetY - ball.y) * easing;
ball.x += vx;
ball.y += vy;
ball.draw(context);
} ())
}
</script>
</body>
</html>
javascript部分:
// ball.js
var utils = {
parseColor: function (color, toNumber) {
if (toNumber === true) {
if (typeof color === 'number') {
return (color | 0);
}
if (typeof color === 'string' && color[0] === '#') {
color = color.slice(1);
}
return window.parseInt(color, 16);
}
else {
if (typeof color === 'number') {
color = '#' + ('0000' + (color | 0).toString(16)).substr(-6);
}
return color;
}
}
};
function Ball (radius, color) {
color = color || '#ff0000';
this.radius = radius;
this.color = utils.parseColor(color);
this.x = 0;
this.y = 0;
this.rotation = 0;
this.vx = 0;
this.vy = 0;
this.scaleX = 1;
this.scaleY = 1;
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.beginPath();
context.arc(0, 0, this.radius, 0, (Math.PI * 2), true);
context.closePath();
context.fill();
if (this.lineWidth > 0) {
context.stroke();
}
context.restore();
}
至此我们已经学习完了简单的缓动运动。