大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
在一些动画设置中,我们可以用CSS中已有的动画属性方便的设置动画效果,比如说animation动画,transition过渡,它们结合一些2D,3D变换可以达到可观的动画效果,但是涉及到更多更加复杂的动画这个时候我们还要基于JavaScript实现。在这里我们定义一个JavaScript中一个实用的函数以便今后的设置。
动画基础
(1)定时器setTimeout
动画的设置是在一个连续间隔的时间内,变换关键帧,在人眼的视觉暂留下连续起来。这个时间间隔如何实现?时间间隔的实现依赖于setTimeout定时器API,今后的动画设置也将基于这个API。
setTimeout能够让某个函数在经过一段预定时间之后才开始执行,带有两个参数。第一个参数是要执行函数的名字,第二个参数则是一个数值,表示间隔的时间长短:
使用方法:setTimeout(“function()”,interval)
window.onload=setTimeout("changeNumber()",2000);//2s后调用此函数
function changeNumber()
{
var test=document.getElementById("test");
test.innerHTML="warning!";
}
定时器解除clearTimeout
我们可以像清除浮动那样清除定时器,用clearTimeout(variable).
使用方法:先将定时器赋值给一个变量,然后将这个变量作为clearTimeout的参数:
window.onload=function()
{
var timer=setTimeout("changeNumber()",2000);
clearTimeout(timer);
}
function changeNumber()
{
var test=document.getElementById("test");
test.innerHTML="warning!";
}
这样一来定时就被解除了.
(2)递归函数
既然有了定时器,我们就能基于定时器API来设置动画了。如何设置动画?我们需要在间隔时刻改变目标的位置,直到到达终点,只要这个间隔足够小,人眼就会将其视为连续的平滑动画。我决定定义一个moveElement函数,在间隔时刻改变目标的位置直到到达终点:
function moveElement(elementId,final_x,final_y,interval)
{
if(!document.getElementById) return false;
if(!document.getElementById(elementId)) return false;
var elem=document.getElementById(elementId);
var x=parseInt(elem.style.left);
var y=parseInt(elem.style.top);
if(x==final_x&&y==final_y) return true;//边界条件
if(x<final_x){
x++;}
if(x>final_x){
x--;}
if(y<final_y){
y++;}
if(y>final_y){
y--;}
elem.style.left=x+"px";
elem.style.top=y+"px";
var repeat="moveElement('"+elementId+"',"+final_x+","+final_y+","+interval+")";
timer=setTimeout(repeat,interval);//定时器设置,递归调用
}
这个函数用简单的递归调用实现。我们要注意一个问题,就是elem.style属性是elem标签的内联样式,而不是css中的id,class中的属性。一旦想使用style未初始化那么这个时候style中变量的值为NAN,所以想使用style中变量的值,有两个办法:
(1)行内初始化:
<p id="test" style="top: 0px;left:0px;" >Hello World!</p>
<script src="test.js"></script>
(2)DOM初始化
我们定义一个初始化的函数,用这个函数给style属性初始化,或者直接在moveElement函数内部初始化:
function positionessage(elementId,first_x,first_y)
{
if(!document.getElementById) return false;
var elem=document.getElementById(elementId);
elem.style.position="absoluate";
elem.style.left=first_x+"px";
elem.style.top=first_y+"px";
}
用动画增强网页效果
以上我们得到了一个动画函数,这个函数可以使我们的元素沿着任意方向移动,现在我们利用这个函数做一些更加是用的应用来增强我们的网页。
我们仍然看图片库这个例子:图片库
我们想当鼠标悬停在某个图片上时,下方的图片会更新,这样一来我们就能有一个预览效果。有一个简单的处理方法——将onclick改为onmouseover这样鼠标悬停就会得到响应。
function prepareGallery()
{
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById("photoGallery")) return false;
var gallery=document.getElementById("photoGallery");
var links=gallery.getElementsByTagName("a");
for(var i=0;i<links.length;i++)
{
links[i].onmouseover=function()
{
return !showPic(this);//调用showPic函数
}
links[i].onkeypress=links[i].onmouseover;
}
}
但是这样处理的缺点是响应不够顺畅,因为需要将新的图片加载上去难免会花费时间,我们想要的是更快更流畅的效果:
- 设置一张长图,这张长图将所有的图片横向包含
- 隐藏这张长图的绝大部分
- 当鼠标悬浮时,显示这张图的相应子图
(1)用CSS隐藏其他部分
现在整张图片都是可见的,我们想只展示一个400px宽,300px高的固定区域,而隐藏其他区域。用JavaScript无法做到这一点,但是我们可以用CSS的overflow属性来设置:
盒子模型溢出处理overflow
分量 | 描述 |
---|---|
visible | 溢出全部可见 |
hidden | 隐藏,超出部分不可见 |
scroll | 显示滚动条 |
auto | 如果有超出,显示滚动条 |
(2) 设置偏移动画
现在我们可以将其余部分隐藏了,但是要达到浏览的效果,我们必须能够将其他部分展现出来。可以给图片设置一个偏移的效果,这样一来就能浏览到其他区域了,如何设置偏移呢?也许你会想到style.backgroundPositionX属性,但是这里我们用前面定义的动画函数moveElement.
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Photo Gallery</title>
<link rel="stylesheet" type="text/css" href="photo gallery.css">
<script src="photo gallery.js"></script>
</head>
<body>
<h1>Photo Gallery</h1>
<ul id="linkList">
<li><a href="images/1.png" title="基普乔格1"><img src="images/1.png" width="55" height="45"></a></li>
<li><a href="images/2.png" title="基普乔格2"><img src="images/2.png" width="55" height="45"></a></li>
<li><a href="images/3.png" title="基普乔格3"><img src="images/3.png" width="55" height="45"></a></li>
<li><a href="images/4.png" title="贝克勒1"><img src="images/4.png" width="55" height="45"></a></li>
<li><a href="images/5.png" title="贝克勒2"><img src="images/5.png" width="55" height="45"></a></li>
<li><a href="images/6.png" title="贝克勒3"><img src="images/6.png" width="55" height="45"></a></li>
</ul>
<div id="slidShow">
<img src="images/test.jpg" alt="Choos a picture" id="preview" />
</div>
</body>
</html>
JavaScript:
function addLoadEvent(func)
{
var oldonload=window.onload;
if(typeof window.onload!='function')//未被绑定
{
window.onload=func;
}
else
{
window.onload=function()//匿名函数添加
{
oldonload();
func();
}
}
}
addLoadEvent(prepareSlidshow);
function prepareSlidshow()
{
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
if(!document.getElementById("linkList")) return false;
if(!document.getElementsByTagName("preview")) return false;
var preview=document.getElementById("preview");
preview.style.position="absolute";
preview.style.left="0px";
preview.style.top="0px";
var list=document.getElementById("linkList");
var links=list.getElementsByTagName("a");
/* for(var i=0;i<links.length;i++) { links[i].οnmοuseοver=function() { var move=-(i+1)*400; moveElement("preview",move,0,10); } } */
links[0].onmouseover=function()
{
var move=0;
moveElement("preview",move,0,0.01);
}
links[1].onmouseover=function()
{
var move=-400;
moveElement("preview",move,0,0.01);
}
links[2].onmouseover=function()
{
var move=-800;
moveElement("preview",move,0,0.01);
}
links[3].onmouseover=function()
{
var move=-1200;
moveElement("preview",move,0,0.01);
}
links[4].onmouseover=function()
{
var move=-1600;
moveElement("preview",move,0,0.01);
}
links[5].onmouseover=function()
{
var move=-2000;
moveElement("preview",move,0,0.01);
}
links[6].onmouseover=function()
{
var move=-2400;
moveElement("preview",move,0,0.01);
}
}
function moveElement(elementId,final_x,final_y,interval)
{
if(!document.getElementById) return false;
if(!document.getElementById(elementId)) return false;
var elem=document.getElementById(elementId);
var x=parseInt(elem.style.left);
var y=parseInt(elem.style.top);
if(x==final_x&&y==final_y) return true;//边界条件
if(x<final_x){
x++;}
if(x>final_x){
x--;}
if(y<final_y){
y++;}
if(y>final_y){
y--;}
elem.style.left=x+"px";
elem.style.top=y+"px";
var repeat="moveElement('"+elementId+"',"+final_x+","+final_y+","+interval+")";
timer=setTimeout(repeat,interval);//定时器设置,递归调用
}
(3)累积事件处理
在上面的过程中我们历遍所有超链接,并且当鼠标悬浮在图片上方时,给长图设置偏移的动画moveElement,注意不能用循环处理,因为循环是一次性的,不能达到任意时刻悬浮都能移动的效果!乍一看移动效果是实现了,但是似乎有一些问题,当两个方向的图片都被悬浮的时候,图片没有移动而是来回振动,问题出在哪?
积累事件: 当图片被鼠标悬停时,moveElement函数被调用,movement计时器执行,而另一张图片被悬停时,第二个movement计时器也被执行,这个时候图片就无法确定执行谁,从而出现了错乱。
清除积累事件
我们想在moveElement函数内部添加一些东西,moveElement执行的时候,要将已有的timer清除:
方法1:定义全局变量
var timer;//定义全局变量
function moveElement(elementId,final_x,final_y,interval)
{
if(!document.getElementById) return false;
if(!document.getElementById(elementId)) return false;
var elem=document.getElementById(elementId);
var x=parseInt(elem.style.left);
var y=parseInt(elem.style.top);
if(timer) clearTimeout(timer);
if(x==final_x&&y==final_y) return true;//边界条件
if(x<final_x){
x++;}
if(x>final_x){
x--;}
if(y<final_y){
y++;}
if(y>final_y){
y--;}
elem.style.left=x+"px";
elem.style.top=y+"px";
var repeat="moveElement('"+elementId+"',"+final_x+","+final_y+","+interval+")";
timer=setTimeout(repeat,interval);//定时器设置,递归调用
}
方法二:增加属性值
JavaScript允许我们创建新的属性:elem.property=value
我们可以给元素设置属性timer,如果存在属性那么就清除,否则直接执行:
function moveElement(elementId,final_x,final_y,interval)
{
if(!document.getElementById) return false;
if(!document.getElementById(elementId)) return false;
var elem=document.getElementById(elementId);
var x=parseInt(elem.style.left);
var y=parseInt(elem.style.top);
if(elem.timer) clearTimeout(elem.timer);
if(x==final_x&&y==final_y) return true;//边界条件
if(x<final_x){
x++;}
if(x>final_x){
x--;}
if(y<final_y){
y++;}
if(y>final_y){
y--;}
elem.style.left=x+"px";
elem.style.top=y+"px";
var repeat="moveElement('"+elementId+"',"+final_x+","+final_y+","+interval+")";
elem.timer=setTimeout(repeat,interval);//定时器设置,递归调用
}
添加属性值的方法似乎更为安全,封装好的moveElement函数非常具有使用意义。
(4)改进变化趋势
我们的moveElement函数每次前进1px,你是否感觉太过于单调?现在我想给它设置一些变化,根据区域到目标的距离来变换,距离越远变化越快,越近变化越慢:
function moveElement(elementId,final_x,final_y,interval)
{
if(!document.getElementById) return false;
if(!document.getElementById(elementId)) return false;
var elem=document.getElementById(elementId);
var x=parseInt(elem.style.left);
var y=parseInt(elem.style.top);
if(elem.timer) clearTimeout(elem.timer);
if(x==final_x&&y==final_y) return true;//边界条件
var dis_x,dis_y;
dis_x=Math.ceil((final_x-x)/10);//向上取整
x+=dis_x;
//round向下取整
dis_y=Math.ceil((final_y-y)/10);//向上取整
y+=dis_y;
elem.style.left=x+"px";
elem.style.top=y+"px";
var repeat="moveElement('"+elementId+"',"+final_x+","+final_y+","+interval+")";
elem.timer=setTimeout(repeat,interval);//定时器设置,递归调用
}
这将会是一个不错的选择
(5)生成HTML标记添加安全检查
前面的slidShow区域是专门为JavaScript服务的,考虑平稳退化时,JavaScript如果不被支持那么网页是否能够平稳退化?但暗示不会,当网页禁用JavaScript,我们的区域将会是一个不可更改的区域,这样的区域将毫无用处因为他的图片是固定的,这意味着我们未能平稳退化,所以我们要将JavaScript完全分离:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Photo Gallery</title>
<link rel="stylesheet" type="text/css" href="photo gallery.css">
<script src="photo gallery.js"></script>
</head>
<body>
<h1>Photo Gallery</h1>
<ul id="linkList">
<li><a href="images/1.png" title="基普乔格1"><img src="images/1.png" width="55" height="45"></a></li>
<li><a href="images/2.png" title="基普乔格2"><img src="images/2.png" width="55" height="45"></a></li>
<li><a href="images/3.png" title="基普乔格3"><img src="images/3.png" width="55" height="45"></a></li>
<li><a href="images/4.png" title="贝克勒1"><img src="images/4.png" width="55" height="45"></a></li>
<li><a href="images/5.png" title="贝克勒2"><img src="images/5.png" width="55" height="45"></a></li>
<li><a href="images/6.png" title="贝克勒3"><img src="images/6.png" width="55" height="45"></a></li>
</ul>
</body>
</html>
JavaScript:
function prepareSlidshow()
{
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
if(!document.getElementById("linkList")) return false;
if(!document.getElementsByTagName("preview")) return false;
var slideShow=document.createElement("div");
slideShow.setAttribute("id","slideShow");
var preview=document.createElement("img");
preview.setAttribute("src","images/test.jpg");
preview.setAttribute("alt","Choose a picture");
preview.setAttribute("id","preview");
slideShow.appendChild(preview);
var list=document.getElementById("linkList");
insertAfter(slideShow,list);
var preview=document.getElementById("preview");
preview.style.position="absolute";
preview.style.left="0px";
preview.style.top="0px";
var links=list.getElementsByTagName("a");
/* for(var i=0;i<links.length;i++) { links[i].οnmοuseοver=function() { var move=-(i+1)*400; moveElement("preview",move,0,10); } } */
links[0].onmouseover=function()
{
var move=0;
moveElement("preview",move,0,15);
}
links[1].onmouseover=function()
{
var move=-400;
moveElement("preview",move,0,15);
}
links[2].onmouseover=function()
{
var move=-800;
moveElement("preview",move,0,15);
}
links[3].onmouseover=function()
{
var move=-1200;
moveElement("preview",move,0,15);
}
links[4].onmouseover=function()
{
var move=-1600;
moveElement("preview",move,0,15);
}
links[5].onmouseover=function()
{
var move=-2000;
moveElement("preview",move,0,15);
}
}
可以达到同样的效果:
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/184857.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...