<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> a{ text-decoration: none; } a:hover{ text-decoration: underline; } ul{ position: relative; } li{ position: absolute; transition: 1s top; } </style> </head> <body> <!-- 上移下移 需求: 1)点击上移就将当前的按钮的父级上移一位 2)当点击第一个时候将当前按钮的父级移动到最后一位 3)当点击最后一个时候将当前按钮的父级移动到首位 跨展板: 移动时带动画 --> <ul id="oUl"> <li>第一项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li> <li>第二项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li> <li>第三项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li> <li>第四项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li> <li>第五项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li> </ul> <script src="getId.js"></script> <script src="doMove.js"></script> <script src="main.js"></script> </body> </html>
var oUl = $('oUl'); var oLi = oUl.getElementsByTagName('li'); for( var i=0, oLen=oLi.length; i<oLen; i++ ){ oLi[i].style.top = (i*16 + i*6) + 'px'; } for(var i=0, oLen=oLi.length; i<oLen; i++){ oLi[i].getElementsByTagName('a')[0].onclick = function(){ var returnValue = moveUp( this.parentNode ); ( !returnValue ) && ( oUl.appendChild( this.parentNode ) ); } oLi[i].getElementsByTagName('a')[1].onclick = function(){ var oldTop = this.parentNode.style.top; // console.log( getSiEle( this.parentNode , 1 ) ); var nextTop = getSiEle( this.parentNode , 1 ).style.top; this.parentNode.style.top = nextTop; getSiEle( this.parentNode , 1 ).style.top = oldTop; var returnValue = moveDown( this.parentNode ); // console.log( returnValue ); // ( !returnValue ) && ( insertBefore( this.parentNode , oUl.children[0] ) ); } }
function $( v ){ if(typeof v === 'function'){ window.onload = v; }else if(typeof v === 'string'){ return document.getElementById( v ); }else if(typeof v === 'object'){ return v; } } function getStyle( obj,attr ){ var arr = ''; for(var i=0; i<attr.length; i++){ if(attr[i] != ' ') arr += attr[i]; } return obj.currentStyle ? obj.currentStyle[arr] : getComputedStyle(obj)[arr]; } function $class(typeEle,attr){ var oChild = document.getElementsByTagName(typeEle); var arr = []; for(var i=0; i<oChild.length; i++){ if( oChild[i].className == attr ){ arr.push(oChild[i]); } } return arr; } function getSiEle( ele , v ){ //-1代表查找前一个兄弟元素,1代表查找后一个兄弟元素 //开始查找前判断本元素是不是第一个元素或最后一个元素,如果是返回false //开始查找 if( v === -1 ){ v = 'previousSibling'; if( ele.parentNode.children[0] == ele ){ return false; } } if( v === 1 ){ v = 'nextSibling'; if( ele == ele.parentNode.children[ ele.parentNode.children.length-1 ] ){ return false; } } var theParent = ele[v]; while( theParent.nodeType != 1 ){ theParent = theParent[v]; } return theParent; } //重新包装一下 function insertBefore( newEle , targetEle ){ targetEle.parentNode.insertBefore( newEle , targetEle ); } //向targetEle后面插入一个元素节点 function insertAfter( newEle , targetEle ){ var tNextSibling = targetEle.nextSibling; var targetEleParent = targetEle.parentNode; if( tNextSibling ){ targetEleParent.insertBefore( newEle , tNextSibling ); }else{ targetEleParent.appendChild( newEle ); } } //上移 function moveUp( ele ){ var tSiEle = getSiEle( ele , -1 ); if( !tSiEle ){ return false; } ele.parentNode.insertBefore( ele , tSiEle ); return true; } //下移 function moveDown( ele ){ var tSiEle = getSiEle( ele , 1 ); if( !tSiEle ){ return false; } insertAfter( ele , tSiEle ); console.log(555); return true; } /* while(true){ if( oDiv[oDiv.length-1] != 400 ){ FdoMove(400); }else{ FdoMove(0); } } function FdoMove(endStep){ document.onclick = function(){ clearInterval(attrs.timer); attrs.timer = setInterval(function(){ if(endStep != 0){ if( parseInt(oDiv[attrs.i].style.top) == endStep ) attrs.i++; if( attrs.i < oDiv.length ){ doMove( oDiv[attrs.i], 'top', 90, endStep ); }else{ clearInterval(attrs.timer); attrs.timer = null; } }else{ if( parseInt(oDiv[attrs.lastNum].style.top) == endStep ) attrs.lastNum--; if( attrs.lastNum >= endStep ){ doMove( oDiv[attrs.lastNum], 'top', 90, endStep ); }else{ clearInterval(attrs.timer); attrs.timer = null; } } },90); } }*/
当var returnValue = moveDown( this.parentNode ); 这句注释掉,两个li可以顺利过渡,但加上这个,其中一条,就是被剪切的那一条没有过渡效果,瞬间位置变化;
我觉得变化位置的时候,改变的是视觉层的li位置。我这么理解:css里给标签加上transition这个样式,相当于是在位置变换的【初始点】~~【最终点】中间补上了过渡帧,而过渡帧需要基于一样 “东西” ,来做,不可能过渡空气,这个 “东西” 就是DOM节点在浏览器上显示的样子( 把页面看成是由许多不一样大小图片组成的 ),而这个“li图片” 是由DOM生成的,浏览器解析是需要先确定下来DOM树,再根据DOM树把节点画出来,再把画出来的骨架和css合成,就是我们在浏览器上看见的样子,而剪切DOM节点,就要重新确定DOM树,重新和CSS合成生成,就是这个生成过程,【我觉得】:首先是按css设置的优先级先设置好,再解析js,根据js设置的样式去合成。
想这个图,this.parentNode的css文件里的top值是0;getSiEle( this.parentNode , 1 )的css文件里的top值是22px。这两个都是li,css文件里给li设置了 transition: 1s top;【就是当触发的时候,如果top有改变会给它加上过渡动画】,第三句是剪切第一个li到第二个li的下面。这三句话都需要点击才能执行。当点击的时候,两个li改变了【包括,DOM和css合成,再和js合成】,transition也触发了,第一帧顺利走动(可能有两帧,取决于第三句话剪切动作的执行时间),第二帧的时候剪切动作发生了【DOM和css重新合成,DOM再和js重新合成,但第一二句已经不会再执行,它们需要点击触发,所以这里我觉得js是拿上一次的值来用,于是乎,位置设置瞬间完成,生成的 “图片” 和第一帧的完全不一样,transition第二帧起操作的是空气】。
简单一句话就是:对DOM的剪切操作会中断css的transition。
【以上推论纯属个人臆想,属强行解释,没有依据】