《making things move 》第八章

本文深入探讨了运动动画中的Easing和Spring效果实现原理及应用案例,包括如何使用缓冲公式实现平滑移动、透明度变化和旋转等效果,以及通过加速度比例实现弹簧效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《making things move 》第八章
周末这两天休的,休懒了~~~加快速度看~~~

Easing 和 Spring

关于这章,以前webstudio根据这章翻译了一个简明教程:

http://www.nshen.net/blog/article.asp?id=303

Easing :

简单的easing就是我们常说的缓冲公式,就是每次走到目标距离的一半,你永远也到不了目标的那个。。。熟到不行的公式
ball._x += (targetX - ball._x) * easing;
ball._y += (targetY - ball._y) * easing;

例子:鼠标拖动试试

Media 点这里 显示/隐藏 媒体

var easing:Number = 0.2;
var targetX:Number = Stage.width / 2;
var targetY:Number = Stage.height / 2;
var dragging:Boolean = false;
ball.onPress = function()
{
 dragging = true;
 this.startDrag();
}
ball.onRelease = ball.onReleaseOutside = function()
{
 dragging = false;
 this.stopDrag();
}
onEnterFrame = function ()
{
 if(!dragging)
 {
 var vx:Number = (targetX - ball._x) * easing;
 var vy:Number = (targetY - ball._y) * easing;
 ball._x += vx;
 ball._y += vy;
 }
};

需要注意的是,easing 永远到不了终点,还是那句话“每次走到目标距离的一半,你永远也到不了目标”

flash中处理的坐标最小值是一twip,一twip是20分之1象素 ,0.05象素,所以你trace一个mc坐标时候都是0.05的倍数
var targ:Number = 100;
ball._x = 0;
for(var i:Number=0;i<20;i++)
{
 trace(i + ": " + ball._x);
 ball._x += (targ - ball._x) * .5;
}

This just loops through 20 times, moving the ball half the distance to the target. It’s basic easing code. I threw it in a for loop because I was only interested in tracing the positions, not actually seeing the motion. What you’ll find is that by the eleventh iteration, the ball has reached 99.95, and that’s as far as it gets.

In tracing positions, you might also notice that occasionally you get a number like 96.85000000000001. This has to do with the way fractions are stored in a binary format, and has nothing to do with pixels, twips, or Flash itself. For more information, do a web search for “binary round-off errors.”

距离目标足够近的话就假定他已经到了目标
var easing:Number = 0.2;
var targ:Number = Stage.width / 2;
onEnterFrame = ease;
function ease() {
 var dx:Number = targ - ball._x;
 if(Math.abs(dx) < 1)
 {
 ball._x = targ;
 delete onEnterFrame;
 trace("done");
 }
 else
 {
 var vx:Number = dx * easing;
 ball._x += vx;
 }
};

Easing不只可以用在运动上:

透明度

Apply easing to the _alpha property of a clip. Start out by setting it to 0, and making the target 100:

ball._alpha = 0;
var targetAlpha:Number = 100;
Then you can fade it in with easing in an enterFrame handler:

ball._alpha += (targetAlpha − ball._alpha) * easing;
Or reverse the 0 and 100 to make it fade out.

旋转

Set the _rotation property and a target rotation. Of course, you need something that can be visibly rotated, like an arrow:

arrow._rotation = 90;
var targetRotation:Number = 270;
And then ease it:

arrow._rotation += (targetRotation − arrow._rotation) * easing;

颜色
If you are up for a real challenge, try easing on 24-bit colors. You’ll need to start with red, green, and blue initial values and target values, perform the easing on each separate component color, and then combine them into a 24-bit color. For instance, you could ease from red to blue. Start with the initial and target colors:

red = 255;
green = 0;
blue = 0;
redTarget = 0;
greenTarget = 0;
blueTarget = 255;
Then in your enterFrame handler, perform easing on each one. Here is just the red value:

red += (redTarget − red) * easing;
Then combine the three into a single value (as described in Chapter 4):

col = red << 16 | green << 8 | blue;
And use that for setRGB, or for a line, a fill color, or another element.

高级Easing

Robert Penner是这方面专家可以到他网站上看www.robertpenner.com.或自己看看flash中的tween类

Spring

Spring就像弹簧效果

加速度是距离的比例
var spring:Number = 0.1;
ball._x = 0;
ball._y = Stage.height / 2;
var targetX:Number = Stage.width / 2;
var vx:Number = 0;
onEnterFrame = function () {
 var ax:Number = (targetX - ball._x) * spring;
 vx += ax;
 ball._x += vx;
};

Media 点这里 显示/隐藏 媒体


发现停不下来 - -b,不像弹簧了,想想。。。

哦,肯定要加个摩擦力
var spring:Number = 0.1;
var friction:Number = 0.95;
ball._x = 0;
ball._y = Stage.height / 2;
var targetX:Number = Stage.width / 2;
var vx:Number = 0;
onEnterFrame = function () {
 var ax:Number = (targetX - ball._x) * spring;
 vx += ax;
 vx *= friction;
 ball._x += vx;
};

Media 点这里 显示/隐藏 媒体


Spring 到一个移动的目标

var ax:Number = (targetX - ball._x) * spring;
var ay:Number = (targetY - ball._y) * spring;

把target改成鼠标

var ax:Number = (_xmouse - ball._x) * spring;
var ay:Number = (_ymouse - ball._y) * spring;

Media 点这里 显示/隐藏 媒体


Spring 链

Media 点这里 显示/隐藏 媒体


第一个球,跟随鼠标,其他的球跟随前一个,并加一个重力加速度
var spring:Number = 0.1;
var friction:Number = 0.8;
var gravity:Number = 5;
var ballCount:Number = 5;
for(var i=0;i<ballCount;i++)
{
 var ball:MovieClip = attachMovie("ball", "ball" + i, i);
 ball.vx = 0;
 ball.vy = 0;
}
onEnterFrame = function () {
 clear();
 lineStyle(1, 0, 100);
 moveTo(_xmouse, _ymouse);

 ball0.vx += (_xmouse - ball0._x) * spring;
 ball0.vy += (_ymouse - ball0._y) * spring;

 for(var i=0;i<ballCount;i++)
 {
 var ballA:MovieClip = this["ball" + i];
 if(i > 0)
 {
 var ballB:MovieClip = this["ball" + (i-1)];
 ballA.vx += (ballB._x - ballA._x) * spring;
 ballA.vy += (ballB._y - ballA._y) * spring;
 }
 ballA.vy += gravity;
 ballA.vx *= friction;
 ballA.vy *= friction;
 ballA._x += ballA.vx;
 ballA._y += ballA.vy;
 lineTo(ballA._x, ballA._y);
 }
};

Spring到若干目标

Each force is an acceleration, and you just add them on to the velocity, one by one. Well, since a spring is nothing more than something exerting acceleration on an object, it’s pretty simple to create multiple springs acting on a single object.

Media 点这里 显示/隐藏 媒体

var spring:Number = 0.1;
var friction:Number = 0.9;
var vx:Number = 0;
var vy:Number = 0;

handle0.onPress = doDrag;
handle0.onRelease = handle0.onReleaseOutside = doDrop;
handle1.onPress = doDrag;
handle1.onRelease = handle1.onReleaseOutside = doDrop;
handle2.onPress = doDrag;
handle2.onRelease = handle2.onReleaseOutside = doDrop;

onEnterFrame = function () {
 vx += (handle0._x - ball._x) * spring;
 vy += (handle0._y - ball._y) * spring;

 vx += (handle1._x - ball._x) * spring;
 vy += (handle1._y - ball._y) * spring;

 vx += (handle2._x - ball._x) * spring;
 vy += (handle2._y - ball._y) * spring;

 vx *= friction;
 vy *= friction;
 ball._x += vx;
 ball._y += vy;

 clear();
 lineStyle(1, 0, 100);
 moveTo(ball._x, ball._y);
 lineTo(handle0._x, handle0._y);
 moveTo(ball._x, ball._y);
 lineTo(handle1._x, handle1._y);
 moveTo(ball._x, ball._y);
 lineTo(handle2._x, handle2._y);
};

function doDrag()
{
 this.startDrag();
}
function doDrop()
{
 this.stopDrag();
}

偏移:

attachments/200611/07_100756_1.jpg

var spring:Number = 0.1;
var friction:Number = 0.9;
var springLength:Number = 75;
var vx:Number = 0;
var vy:Number = 0;

onEnterFrame = function () {
 var dx:Number = ball._x - _xmouse;
 var dy:Number = ball._y - _ymouse;
 var angle:Number = Math.atan2(dy, dx);
 var targetX:Number = _xmouse + Math.cos(angle) * springLength;
 var targetY:Number = _ymouse + Math.sin(angle) * springLength;
 vx += (targetX - ball._x) * spring;
 vy += (targetY - ball._y) * spring;

 vx *= friction;
 vy *= friction;
 ball._x += vx;
 ball._y += vy;

 clear();
 lineStyle(1, 0, 100);
 moveTo(ball._x, ball._y);
 lineTo(_xmouse, _ymouse);
};

Media 点这里 显示/隐藏 媒体


若干object的spring

Media 点这里 显示/隐藏 媒体

var spring:Number = 0.1;
var friction:Number = 0.9;
var springLength:Number = 75;
ball0.vx = 0;
ball0.vy = 0;
ball0.onPress = doDrag;
ball0.onRelease = ball0.onReleaseOutside = doDrop;
ball1.vx = 0;
ball1.vy = 0;
ball1.onPress = doDrag;
ball1.onRelease = ball1.onReleaseOutside = doDrop;

onEnterFrame = function () {
 springTo(ball0, ball1);
 springTo(ball1, ball0);
 clear();
 lineStyle(1, 0, 100);
 moveTo(ball0._x, ball0._y);
 lineTo(ball1._x, ball1._y);
}

function springTo(ballA, ballB)
{
 if(!ballA.dragging)
 {
 //ballB是中点
 var dx:Number = ballA._x - ballB._x;
 var dy:Number = ballA._y - ballB._y;
 var angle:Number = Math.atan2(dy, dx);
 var targetX:Number = ballB._x +
 Math.cos(angle) * springLength;
 var targetY:Number = ballB._y +
 Math.sin(angle) * springLength;
 ballA.vx += (targetX - ballA._x) * spring;
 ballA.vy += (targetY - ballA._y) * spring;
 ballA.vx *= friction;
 ballA.vy *= friction;
 ballA._x += ballA.vx;
 ballA._y += ballA.vy;
 }
};

function doDrag()
{
 this.dragging = true;
 this.startDrag();
}
function doDrop()
{
 this.dragging = false;
 this.stopDrag();
}

相同点:

You set a target.

You determine the distance to that target.

Your motion is proportional to that distance—the bigger the distance, the more the motion.

不同点:

The difference between easing and springing is in what aspect of the motion is proportional. In easing, velocity is proportional to the distance; the further away from the target, the faster the object moves. As it gets very, very close to the object, it’s hardly moving at all.

In springing, acceleration is proportional to the distance. If the object is far away from the target, a whole lot of acceleration is applied, increasing the velocity quickly. As the object gets closer to its target, less acceleration is applied, but it’s still accelerating! It flies right past the target, and then acceleration pulls it back. Eventually, friction causes it to settle down.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值