需求
上移下移
需求:
1)点击上移就将当前的按钮的父级上移一位
2)当点击第一个时候将当前按钮的父级移动到最后一位
3)当点击最后一个时候将当前按钮的父级移动到首位
4)带过渡动画
需求分析:
下移:剪切所点击的条目插入到下一条目后面
上移:剪切所点击的条目插入到上一条目前面
过渡效果实现:CSS3的transition 或 js实现
实现思路:
transition实现方法,先在CSS里设置好transition: 1s top; 这个样式,然后鼠标点击修改top值触发过渡效果。
需要用js给每一个li设置top值,因为insertBefore会中断transition所以还必须设个定时器,等到过渡结束再执行DOM层面的剪切
难点:
边界的判断:当第一项点击上移是应该移动到最下面其他都上移一层
当最后一项点击下移时应该移动到最上面其他都下移一层
insertBefore为什么会中断transition的执行???
难点解决方案:
前两项都可以解决
最后一项想不通!!!???
涉及的新知识:
element.priviousSibling
element.nextSibling
element.parentNode
element.nodeType
parentNode.insertBefore( newEle , targetEle );
优化方向:
不用定时器也能实现DOM层面和视觉层面一起上移下移且有过渡动画
修复连续点击的bug
封装成一个函数
备注:
写完这个,稍微有点懂得【视觉层】和【行为层】分开的意义了,也稍微感觉到了一点React的数据驱动视图了。其实页面上看到的天花乱坠,DOM里可能啥都每变,看起来div在那个div的上门,其实是用css强行改变它们的默认排列的,所以要从DOM的视角看问题。
最后:为什么insertBefore会中断transition????
<!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: .5s 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‘; //****上移按钮 oLi[i].getElementsByTagName(‘a‘)[0].onclick = function(){ var oldTop = null, nextTop = null, nextItem = getSiEle( this.parentNode , -1 ); //点击第一项要做的事 if( !nextItem ){ nextTop = oUl.children[oUl.children.length-1].style.top; //2~5项向上移1格 for( var j=oUl.children.length-1; j>0; j-- ){ oLi[j].style.top = oLi[j-1].style.top; } this.parentNode.style.top = nextTop; }else{ //如果不是最后一项就两两对换 oldTop = this.parentNode.style.top; nextTop = getSiEle( this.parentNode , -1 ).style.top; this.parentNode.style.top = nextTop; getSiEle( this.parentNode , -1 ).style.top = oldTop; } //等0.5s的transition结束后在执行DOM剪切操作 var _this = this; setTimeout(function(){ if( !moveUp( _this.parentNode ) ){ oUl.appendChild( _this.parentNode ) } },500); } //****上移按钮结束****// //****下移按钮开始 oLi[i].getElementsByTagName(‘a‘)[1].onclick = function(){ var oldTop = null, nextTop = null, nextItem = getSiEle( this.parentNode , 1 ); //点击最后第一项要做的事 if( !nextItem ){ nextTop = oUl.children[0].style.top; //1~4项的位置下降“1格” for(var j=0,oLen=oUl.children.length; j<oLen-1; j++ ){ oLi[j].style.top = oLi[j+1].style.top } //点击项升到顶端 this.parentNode.style.top = nextTop; }else{ //如果不是最后一项就两两对换 oldTop = this.parentNode.style.top; nextTop = getSiEle( this.parentNode , 1 ).style.top; this.parentNode.style.top = nextTop; getSiEle( this.parentNode , 1 ).style.top = oldTop; } //等0.5s的transition结束后在执行DOM剪切操作 var _this = this; setTimeout(function(){ if( !moveDown( _this.parentNode ) ){ insertBefore( _this.parentNode , oUl.children[0] ); } },500); } //****下移按钮结束****// }
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); } }*/
原文:https://www.cnblogs.com/mflnhg/p/9503309.html