目录
10.1动画基础知识
前面的章节介绍了如何用DOM技术修改文档的样式,但总的来说CSS仍是完成这项任务的最佳工具,不过有一个领域是CSS目前无能为力的。如果我们想随着事件改变某个元素的样式,则只能用JavaScript
位置
网页元素在窗口内的位置是一种表示性的信息,因此位置信息通常是由CSS负责设置的。
在CSS中position属性的合法值有static,fixed,relative和absolute四种。static是position属性的默认值,意思是有关元素按照他们在标记里出现的先后顺序出现在浏览器窗口里。relative的含义和static相似,区别在于他还可以从文档正常的显示顺序中脱离出来通过float属性。如果把一个元素的position属性设置为absolute。我们就可以把它摆放到容纳他的容器的任何位置,这个容器要么是文档本身,要么是一个有着fixed和absolute属性的父元素,这个元素在原始标记里出现的位置和他的显示位置无关,因为他的显示位置由top,left,right和bottom属性决定。
设置和改变某个元素的位置很简单,只需要执行一个函数去改变这个元素的style.top或style.left属性就行了。
但是位置立刻发生变化并不是我们想要的动画效果,要获得动画效果,必须让元素的位置随着时间不断地变化。
时间
JavaScript函数setTimeout可以让某个函数经过一段预定的时间之后才开始执行
setTimeout(‘function’, interval)
第一个参数是要执行的函数,第二个参数是一个数值,以毫秒为单位设定了需要经过多长时间后才开始执行第一个参数所给出的函数。
时间递增量
真正的动画是一个渐变的过程,元素应该从出发点逐步移动到目的地。接下来的moveMessage函数让元素的移动以渐变的方式发生。
function moveElement() {
var elem = document.getElementById('message');
xpos = parseInt(elem.style.left);
ypos = parseInt(elem.style.top);
if (xpos == 200 & ypos == 200) {
return true;
}
if (xpos < 200) {
xpos++;
}
if (xpos > 200) {
xpos--;
}
if (ypos > 200) {
ypos--;
}
if (ypos < 200) {
ypos++;
}
elem.style.top = ypos + 'px';
elem.style.left = xpos + 'px';
movement = setTimeout('moveElement()', 10);
}
function positionMessage() {
var elem = document.getElementById('message');
elem.style.position = 'absolute';
elem.style.top = '50px'
elem.style.left = '100px'
movement = moveElement();
}
抽象
刚才编写的moveElement函数只能完成一项特定的任务,如果把这些常数改为变量,对moveMessage函数进行抽象,则可以让他变得更加通用。
function moveElement(elementID, finalX, finalY, interval) {
var elem = document.getElementById(elementID);
xpos = parseInt(elem.style.left);
ypos = parseInt(elem.style.top);
if (xpos == finalX & ypos == finalY) {
return true;
}
if (xpos < finalX) {
xpos++;
}
if (xpos > finalX) {
xpos--;
}
if (ypos > finalY) {
ypos--;
}
if (ypos < finalY) {
ypos++;
}
elem.style.top = ypos + 'px';
elem.style.left = xpos + 'px';
var repeat = "moveElement('" + elementID + "', " + finalX + ", " + finalY + ", " + interval + ")";
movement = setTimeout(repeat, interval);
}
在以上例子中,所有的工作都是由moveElement函数完成,只需要简单改变一下函数的参数值,就可以随意重用他,这正是抽象的最大好处。
10.2 实用的动画
提出问题
如果我们有一个包含一系列链接的网页,当用户把鼠标指针悬停在其中某个链接上时,我们希望展示一张预览图片。
以下是HTML文档代码
<body>
<h1>Web Design</h1>
<p>these are the tyhings you should know</p>
<ol id='linklist'>
<li><a href="structure.html">Structure</a></li>
<li><a href="presentation.html">Presentation</a></li>
<li><a href="behavior.html">Behavior</a></li>
</ol>
<div id="slideshow">
<img src="catopic.png" alt="Choose a topic" id="preview">
</div>
</body>
接下来对她做一些改进
注意在进行CSS样式设置的时候,div的position要设置为relative(子绝父相),overflow要设置成hidden,确保其中内容会被剪裁
接下来解决的问题就是当用火狐把指针悬停在某个链接上的时候,与之对应的图片才显示出来。
JavaScript
function prepareSlideshow() {
if (!document.getElementById) return false;
if (!document.getElementsByTagName) return false;
var preview = document.getElementById('preview');
preview.style.position = "absolute";
preview.style.left = '0px';
preview.style.top = '0px';
var link = document.getElementById('linklist')
var links = document.getElementsByTagName('a');
links[0].onmouseover = function() {
moveElement('preview', -100, 0, 10);
}
links[1].onmouseover = function() {
moveElement('preview', -200, 0, 10);
}
links[2].onmouseover = function() {
moveElement('preview', -300, 0, 10);
}
}
加入这一串代码后效果不尽人意,如果鼠标指针在各链接上快速移动,动画效果变得混乱起来。
这是因为一个全局变量movement引起的,不管上一次调用是否移动到位,moveElement都会被再次调用并试图把图片移动到另一个地方去。因此当用户在链接之间快速移动的时候,movement变量会像一条拔河绳一样来回变化。
为了消除动画滞后的现象,可以用clearTimeout函数清除积累在setTimeout队列里的时间。
function moveElement(elementID, finalX, finalY, interval) {
var elem = document.getElementById(elementID);
xpos = parseInt(elem.style.left);
ypos = parseInt(elem.style.top);
if (elem.movement) {
clearTimeout(elem.movement);
} //清除事件
if (xpos == finalX & ypos == finalY) {
return true;
}
if (xpos < finalX) {
xpos++;
}
if (xpos > finalX) {
xpos--;
}
if (ypos > finalY) {
ypos--;
}
if (ypos < finalY) {
ypos++;
}
elem.style.top = ypos + 'px';
elem.style.left = xpos + 'px';
var repeat = "moveElement('" + elementID + "', " + finalX + ", " + finalY + ", " + interval + ")";
elem.movement = setTimeout(repeat, interval); //设置属性
}
改进动画效果
如果希望动画效果更加平滑可以更改每次移动的距离,而不是固定为1px,就像这样
if (xpos < finalX) {
dist = Math.ceil((finalX - xpos) / 10);
xpos = xpos + dist;
每一次都会移动到目的点距离的十分之一,就会由快到慢,让动画效果看来更加平滑。
11.HTML5
这一章节对HTML5的一些新的特性和标签做了介绍,和DOM关系不大,留作以后和CSS3一起学习。