运动实现思路
改变left、right、width、height、opacity
做一个侧栏分享的案例
容器设置相对定位。
内容原本的left是负值,设置一个定时器,每隔一段时间,露出一点来。
直至offsetLeft为0,结束计时器。
window.onload=function(){
var oDiv=document.getElementById("div1");
oDiv.onmouseover=function(){
startMove(0);
}
oDiv.onmouseout=function(){
startMove(-200);
}
}
var timer=null;
function startMove(iTarget){
clearInterval(timer);
var oDiv=document.getElementById("div1");
timer=setInterval(function(){
var speed=0;
// 判断该 增 or 减 left
if(oDiv.offsetLeft > iTarget){
speed = -10;
}else{
speed = 10;
}
//判断停止或继续运动
if(oDiv.offsetLeft==iTarget){
clearInterval(timer);
}else{
oDiv.style.left=oDiv.offsetLeft+speed+"px";
}
},30)
}
filter:alpha(opacity:30); 针对 IE8 以及更早的版本 0-100
opacity:0.3; 0~1
跟上面的例子一样,只不过最后操作的属性是透明度。
window.onload=function(){
var oDiv=document.getElementById("div1");
oDiv.onmouseover=function(){
startMove(100);
}
oDiv.onmouseout=function(){
startMove(30);
}
}
var timer=null,
alpha=30;
function startMove(iTarget){
clearInterval(timer);
var oDiv=document.getElementById("div1");
//每次运动时,先把变量speed清零
timer=setInterval(function(){
var speed=0;
if(alpha > iTarget){
speed = -10;
}else{
speed = 10;
}
if(alpha==iTarget){
clearInterval(timer);
}else{
alpha+=speed;
oDiv.style.filter = "alpha(opacity:'+alpha+')";
oDiv.style.opacity = alpha/100;
}
},30)
}
speed = (目标值和当前值的差)/ 数值
当差值大的时候,速度就快。
当差值小的时候,速度就慢。
上面的计算会导致小数点的出现,浏览器是向下取整的小数点一直被忽略。
结果,就会导致一直达不到我们所设定的目标值。
因此,我们需要做一些处理。
window.onload=function(){
var oDiv=document.getElementById("div1");
oDiv.onmouseover=function(){
startMove(0);
}
oDiv.onmouseout=function(){
startMove(-200);
}
}
var timer=null;
function startMove(iTarget){
clearInterval(timer);
var oDiv=document.getElementById("div1");
timer=setInterval(function(){
var speed = (iTarget-oDiv.offsetLeft)/20;
speed = speed>0?Math.ceil(speed):Math.floor(speed);
if(oDiv.offsetLeft==iTarget){
clearInterval(timer);
}else{
oDiv.style.left=oDiv.offsetLeft+speed+"px";
}
},30)
}
遍历需要元素,分别加上事件。
由于是多物体,所以需要区分物体是哪一个,把this作为参数也传进去。
每一个物体都应该有子集专属的定时器,所以在循环体设置定时器。
在实际工作中,物体肯定会有边框、内外边距。继续使用offset类的属性,将会导致bug出现,所以我们需要获取物体自身的宽高等尺寸属性。
在代码内,封装了一个getStyle方法,IE是通过currentStyle属性获取元素属性的,而其余浏览器则是通过getComputedStyle()方法取得元素属性的。
window.onload=function(){
var aLi = document.getElementsByTagName("li");
//遍历元素
for(var i=0;i//每个元素都创建自己的定时器为null
aLi[i].timer=null;
aLi[i].onmouseover=function(){
//this作为参数传入
startMove(this,400);
}
aLi[i].onmouseout=function(){
startMove(this,200);
}
}
}
//获取属性
function getStyle(obj,attr){
if(obj.currentStyle){ //ie
return obj.currentStyle[attr];
}
else{ //W3C
return getComputedStyle(obj,false)[attr];
}
}
function startMove(obj,iTarget){
//清除定时器
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var icur = parseInt(getStyle(obj,'width'));
var speed = (iTarget-icur)/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);
if(icur==iTarget){
clearInterval(obj.timer);
}else{
obj.style.width = icur+speed+"px";
}
},30)
}
在运动函数内加一个参数,让它执行一个回调函数。
<html>
<head>
<meta charset="utf-8">
<title>链式动画title>
<style>
*{
margin:0;
padding:0;
}
ul,li {
list-style:none;
}
ul li {
width:200px;
height:100px;
background:yellow;
margin-bottom:20px;
border:4px solid #000;
filter:alpha(opacity:30);
opacity:0.3;
}
style>
<script>
window.onload=function(){
var Li=document.getElementById('li1');
Li.onmouseover= function(){
startMove(Li,'width',400,function(){
alert("done");
});
}
}
function getStyle(obj, atttr) {
if(obj.currentStyle) {
return obj.currentStyle[atttr];
} else {
return getComputedStyle(obj, false)[atttr];
}
}
function startMove(obj, attr, iTarget, fn) {
clearInterval(obj.timmer);
obj.timmer = setInterval(function() {
var icur = 0;
if(attr == 'opacity') {
icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
} else {
icur = parseInt(getStyle(obj, attr));
}
var speed = (iTarget - icur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(icur == iTarget) {
clearInterval(obj.timmer);
if(fn) {
fn();
}
} else {
if(attr == 'opacity') {
obj.style.opacity = (icur + speed) / 100;
} else {
obj.style[attr] = (icur + speed) + 'px';
}
}
}, 30);
}
script>
head>
<body>
<ul>
<li id="li1">li>
ul>
body>
html>
这一版方案存在以下问题:
在屏幕缩放比例为非100%的时候,有可能会导致元素计算宽度问题,从而导致最终无法进行链式运动。
解决思路:
1. 既然是屏幕缩放比例出现问题,那我首先可以提醒一下用户,请他把屏幕分辨率调整为100%
如果是Chrome和FireFox,可以使用window.devicePixelRatio接口查询;
IE使用window.screen.deviceXDPI 和 window.screen.logicalXDPI ;
其他浏览器使用window.outerWidth 和 window.innerWidth 这两个属性。
2. 使用rem相对单位
使用rem相对单位,并且把iTarget变为函数内部变量,传入参数改变为倍数。
这里面有一个问题,getStyle函数获取属性的单位是px,而不是rem,所以需要对icur变量进行处理。
由于现在iTarget是不固定的值,判断条件应该改为icur和最终值的比较。
<html>
<head>
<meta charset="utf-8">
<title>链式动画title>
<style>
*{
margin:0;
padding:0;
}
html {
font-size:20px;
}
ul,li {
list-style:none;
}
ul li {
width:10rem;
height:5rem;
background:yellow;
margin-bottom:20px;
border:4px solid #000;
filter:alpha(opacity:30);
opacity:0.3;
}
style>
<script>
window.onload=function(){
detectZoom ();
var Li=document.getElementById('li1');
Li.onmouseover= function(){
startMove(Li,'width',2,function(){
alert("done");});
}
}
function detectZoom (){
var ratio = 0,
screen = window.screen,
ua = navigator.userAgent.toLowerCase();
if (window.devicePixelRatio !== undefined) {
ratio = window.devicePixelRatio;
}
else if (~ua.indexOf('msie')) {
if (screen.deviceXDPI && screen.logicalXDPI) {
ratio = screen.deviceXDPI / screen.logicalXDPI;
}
}
else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
ratio = window.outerWidth / window.innerWidth;
}
if (ratio){
if(ratio !=1){
alert("为了您的使用体验,请把浏览器缩放比例调整至100%");
}
}
}
function getStyle(obj, atttr) {
if(obj.currentStyle) {
return obj.currentStyle[atttr];
} else {
return getComputedStyle(obj, false)[atttr];
}
}
function startMove(obj, attr, beishu, fn) {
clearInterval(obj.timmer);
obj.timmer = setInterval(function() {
var icur = 0;
if(attr == 'opacity') {
icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
} else {
icur = parseInt(getStyle(obj, attr))/20;
}
var iTarget = icur*beishu;
var speed = (iTarget - icur) / 15;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(icur >= 20 ) {
clearInterval(obj.timmer);
if(fn) {
fn();
}
} else {
if(attr == 'opacity') {
obj.style.opacity = (icur + speed) / 100;
} else {
obj.style[attr] = (icur + speed) + 'em';
}
}
}, 30);
}
script>
head>
<body>
<ul>
<li id="li1">li>
ul>
body>
html>
使用json储存我们的属性和目标值。
另外,停止条件改为所有属性变为目标值。为此,我们声明一个变量flag,还有属性未达到目标值,flag为false,不能停止。
<html>
<head>
<meta charset="utf-8">
<title>同时运动title>
<style>
*{
margin:0;
padding:0;
}
ul,li {
list-style:none;
}
ul li {
width:200px;
height:100px;
background:yellow;
margin-bottom:20px;
border:4px solid #000;
filter:alpha(opacity:30);
opacity:0.3;
}
style>
<script>
window.onload=function(){
var oLi=document.getElementById("li1");
oLi.onmouseover=function(){
startMove(oLi,{width:400,height:201,opacity:100});
}
oLi.onmouseout=function(){
startMove(oLi,{width:200,height:100,opacity:30});
}
}
function getStyle(obj,attr){
if(obj.currentStyle){ //ie
return obj.currentStyle[attr];
}
else{ //W3C
return getComputedStyle(obj,false)[attr];
}
}
function startMove(obj,json,fn){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var flag = true;//假设所有的运动都到达了目标值
for(var attr in json){
//1.取当前的值
var icur=0;
if(attr == 'opacity'){
icur = Math.round(parseFloat(getStyle(obj,attr))*100);
}
else{
icur = parseInt(getStyle(obj,attr));
}
//2.算速度
var speed = (json[attr]-icur)/8;
speed = speed>0?Math.ceil(speed):Math.floor(speed);
//3.检测停止
if(icur!=json[attr]){ //如果不是所有的目标都到达目标值
flag = false;
}
if(attr == 'opacity')
{
obj.style.filter = 'alpha(opacity:'+(icur+speed)+')';
obj.style.opacity=(icur+speed)/100;
}
else
{
obj.style[ attr] = icur+speed+"px";
}
}
if(flag)
{
clearInterval(obj.timer);
if(fn){
fn();
}
}
},30)
}
script>
head>
<body>
<ul>
<li id="li1">li>
ul>
body>
html>