一、开篇
在上一篇中,似乎不出来这个框架有多强大。是因为我们实现的效果太简单了,还不足以体现框架的强大和灵活,在这一节中,用这个灵活的框架轻易的来实现拖放!

二、原理
框架的原理在上一篇文章中介绍了,这里就不在重复,直接开始使用这个框架了
首先通过Drag.init来注册拖动组件;
分析:
1、拖动开始的时候
将dragGhost插入到鼠标拖动的那个元素,鼠标拖动的元素的position为absolute
dragGhost为拖动过程中指示拖动元素的当前位置的元素
2、拖动正在进行的时候
根据当前鼠标的位置或者正在被鼠标拖动的元素的位置 和需要排列的各种元素来比较,以确定将dragGhost放在哪个地方。
具体的分析,就是遍历拖动元素的各个兄弟元素,从第一元素起,一旦发现某个元素的x和y比鼠标的x和y大的话,则将dragGhost添加到这个元素之前。
3、拖动结束的时候
将dragGhost替换为被拖动的元素,然后将dragGhost隐藏。
这样就让思路很清晰,不必再花精力去管元素是怎么随着鼠标走的,而且我们的却很精确的控制了整个拖放过程,所以说这个框架很强大很灵活
三、代码

Code
function findPosX(obj) {//辅助函数 得到元素左边与浏览器左边的边距
var curleft = 0;
if (obj && obj.offsetParent) {
while (obj.offsetParent) {
curleft += obj.offsetLeft;
obj = obj.offsetParent;
}
} else if (obj && obj.x) curleft += obj.x;
return curleft;// + document.body.scrollLeft - document.body.clientLeft;
}
function findPosY(obj) {//辅助函数 得到元素上边与浏览器上边的边距
var curtop = 0;
if (obj && obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop;
obj = obj.offsetParent;
}
} else if (obj && obj.y) curtop += obj.y;
return curtop;// + document.body.scrollTop - document.body.clientTop;
}
var dragGhost;
var container;
window.onload = function(){
dragGhost = document.getElementById("dragGhost");
container = document.getElementById("container");
var nodes = container.getElementsByTagName("li");
for(var i=0;i<nodes.length;i++){
var li = nodes[i];
if(li.id != "dragGhost"){
new dragItem(li);
}
}
}
var isIE = document.all;
function dragItem(item){
Drag.init(item,item);
item.onDragStart = function(left,top,mouseX,mouseY){
this.style.left = findPosX(this);
this.style.top = findPosY(this);
this.style.position = "absolute";
//将ghost插入到当前位置
dragGhost.style.display = "block";
dragGhost.style.width = isIE?this.offsetWidth:this.offsetWidth - 2;//边框问题
dragGhost.style.height = isIE?this.offsetHeight:this.offsetHeight - 2;
this.parentNode.insertBefore(dragGhost,this);
}
item.onDrag = function(left,top,mouseX,mouseY){
var nodes = container.getElementsByTagName("li");
var width = this.offsetWidth;
var height = this.offsetHeight;
for(var i=0;i<nodes.length + 1;i++){
if(nodes[i] == null){
container.appendChild(dragGhost);//拖动最后一项
break;
}
if(nodes[i].id == "dragGhost" || nodes[i] == this){
continue;
}
if(mouseX < findPosX(nodes[i]) + width
&& mouseY < findPosY(nodes[i]) + height){
container.insertBefore(dragGhost,nodes[i]);
break;
}
}
}
item.onDragEnd = function(left,top,mouseX,mouseY){
container.insertBefore(this,dragGhost);
this.style.position = "static";
this.style.display = "block";
dragGhost.style.display = "none";
}
}
四、示例下载
点此下载示例
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架