缓动,学名为Tween,缓冲移动的简称。要想页面内容切换起来舒服,就使用淡入淡出特效,要想让页面元素动起来自然,就要使用缓动效果。这两个混合起来,可以衍生多种特效的。感谢Flash开发人员为我们做了那么多先行研究,我们直接把它们拆出来装在各种菜单与相册中。我们先从最简单的东西做起,加速与减速。
既然是缓动,它就一定涉及以下概念:距离,时间与速度。我们可以想象存在一条直线L,点A与点B就是L的起点与终点,有一个点C在直线L上移动,从点A到点B。所需的时间通常都是未知,但速度我们一定要制定。看下面的图,我们想让绿色的方块在淡紧色的滑动带上移动。滑动带左上角就相当于点A,右上角就相当于B点,方块的左上角就相当于点C,移动距离为两者的宽度之差。由于我们移动的物体是存在宽度,也就是说点C永远不可能与点B重合。但一个准确的目的地(为了方便,我们把它称之为点D)是必须的,我们一定要计算它出来。因为在加速运动中,点C随时可能超过点D,当点超过它时,我们就要终止此移动,并把点C拉回到点D上。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<BODY>
<STYLE type=text/css>#taxiway {
BACKGROUND: #e8e8ff; WIDTH: 800px; HEIGHT: 100px
}
#move {
BACKGROUND: #a9ea00; WIDTH: 100px; HEIGHT: 100px
}
</STYLE>
<DIV id=taxiway>
<DIV id=move onclick=move(this)></DIV></DIV>
<P class=notice display="text-align:center">点击可移动绿色方块</P>
<SCRIPT type=text/javascript>
var getCoords = function(el){
var box = el.getBoundingClientRect(),
doc = el.ownerDocument,
body = doc.body,
html = doc.documentElement,
clientTop = html.clientTop || body.clientTop || 0,
clientLeft = html.clientLeft || body.clientLeft || 0,
top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop ) - clientTop,
left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft
return { 'top': top, 'left': left };
};
var getStyle = function(el, style){
if(!+"v1"){
style = style.replace(/-(w)/g, function(all, letter){
return letter.toUpperCase();
});
var value = el.currentStyle[style];
(value == "auto")&&(value = "0px" );
return value;
}else{
return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
}
}
//辅助函数3,相当于$(),不用$符号命名是因为博客园在用JQuery,会引起命名冲突
//我新一代查代元素的方法,拥有缓存能力
var cache = []
var _ = function(id){
return cache[id] || (cache[id] = document.getElementById(id));
}
var move = function(el){
el.style.position = "absolute";
var begin = getCoords(el).left,
distance = parseFloat(getStyle(_("taxiway"),"width")) - parseFloat(getStyle(el,"width")),
end = begin + distance,
speed = 10,//第一次移动的速度,单位px/ms,隐式地乘以1ms
delta = 1.5,
change = true;
el.onclick = function(){
if(change){
el.innerHTML = "加速";
(function(){
setTimeout(function(){
el.style.left = getCoords(el).left + speed + "px";//移动
speed *= delta;//下一次移动的距离
if(getCoords(el).left >= end){
el.style.left = end + "px";
change = false;
delta = 0.85,
speed = 100;
}else{
setTimeout(arguments.callee,25);//每移动一次停留25毫秒
}
},25)
})()
}else{
el.innerHTML = "减速";
(function(){
setTimeout(function(){
el.style.left = getCoords(el).left - speed + "px";//移动
speed = Math.ceil(speed * delta );//下一次移动的距离
if(getCoords(el).left <= begin ){
el.style.left = begin + "px";
change = true;
delta = 1.5,
speed = 10;
}else{
setTimeout(arguments.callee,25);
}
},25)
})()
}
}
}
window.onload = function(){
move(_("move"))
}
</SCRIPT>
</BODY></HTML>
为了获取它们在页面上的坐标与尺寸,getCoords()与getStyle()又到出场时间了。对不起,我实在没有意思来炫耀我的函数。更何况getStyle()被砍去了不少东西,威力没有以前那么强大。
//辅助函数1
var getCoords = function(el){
var box = el.getBoundingClientRect(),
doc = el.ownerDocument,
body = doc.body,
html = doc.documentElement,
clientTop = html.clientTop || body.clientTop || 0,
clientLeft = html.clientLeft || body.clientLeft || 0,
top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop ) - clientTop,
left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft
return { 'top': top, 'left': left };
};
//辅助函数2
var getStyle = function(el, style){
if(!+"v1"){
style = style.replace(/-(w)/g, function(all, letter){
return letter.toUpperCase();
});
var value = el.currentStyle[style];
(value == "auto")&&(value = "0px" );
return value;
}else{
return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
}
}