专栏首页OECOMjs实现拖动组件移动效果

js实现拖动组件移动效果

2015-04-15 14:06:09

今天我来给大家介绍一种js特效,这种特效是当你用鼠标点击组件移动到其他地方后,这个组件就定在了那个地方,这种效果通常用来做视图化排版的。下面我来把代码贴出来给大家看看

 <div id="container">
			<div class="column">
				<div class="item">
					<h3>Header</h3>
					<p>column1 item1</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column1 item2<br />Some text here, so that the height is different!</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column1 item3</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column1 item4</p>
				</div>
			</div>
			<div class="column" style="width:300px;">
				<div class="item">
					<h3>Header</h3>
					<p>column2 item1</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column2 item2</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column2 item3<br />Some text here, so that the height is different!</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column2 item4<br />Some text here, so that the height is different!</p>
				</div>
			</div>
			<div class="column">
				<div class="item">
					<h3>Header</h3>
					<p>column3 item1</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column3 item2</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column3 item3</p>
				</div>
				<div class="item">
					<h3>Header</h3>
					<p>column3 item4</p>
				</div>
			</div>
        </div>

这段代码是html代码,主要是大体的div布局,我们在这里的组件用的是div,通过下面的js代码来实现组件的移动

<script type="text/javascript" src="Drag.js"></script>
        <script type="text/javascript">
//------------------------Utility------------------------
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 = document.createElement("div");
dragGhost.style.border = "dashed 1px #CCCCCC";
dragGhost.style.background = "white";
dragGhost.style.display = "none";
dragGhost.style.margin = "10px";

var container;
var columns = [];
//------------------------Start Here------------------------
window.onload = function(){
	container = document.getElementById("container");
	
	for(var i=0;i<container.childNodes.length;i++){
		if(container.childNodes[i].className == "column"){//筛选出所有的列 ff下的childNodes不可靠 :\
			columns.push(container.childNodes[i]);
		}
	}
	for(var i=0;i<columns.length;i++){
		var column = columns[i];
		for(var j=0;j<column.childNodes.length;j++){
			var item = column.childNodes[j];
			if(item.className == "item"){
				item.column = column;//给每个拖拽对象要指明它属于哪一列 而且这个属性会随着拖动而更新的
				
				new dragItem(item);
			}
		}
	}
}
var isIE = document.all;

//------------------------Drag Item------------------------
function dragItem(item){
	//item实际上是dragBody(拖动的时候移动的整体)
	//在这里需要根据item找到handle(能够拖动的把手)
	
	var handle;
	for(var i=0;i<item.childNodes.length;i++){
		if(item.childNodes[i].nodeName.toLowerCase() == "h3"){
			handle = item.childNodes[i];
			break;
		}
	}
	if(!handle)return;
	Drag.init(handle,item);
	item.onDragStart = function(left,top,mouseX,mouseY){
		//开始拖动的时候设置透明度
		
		this.style.opacity = "0.5";
		this.style.filter = "alpha(opacity=50)";
		dragGhost.style.height = (isIE?this.offsetHeight:this.offsetHeight - 2) + "px";
		
		//this指的是item
		
		this.style.width = this.offsetWidth + "px";//因为初始的width为auto
		this.style.left = (findPosX(this) - 5) + "px";
		this.style.top = (findPosY(this) - 5) + "px";
		this.style.position = "absolute";
		//将ghost插入到当前位置
		dragGhost.style.display = "block";
		this.column.insertBefore(dragGhost,this);
		
		
		//记录每一列的左边距 在拖动过程中判断拖动对象所在的列会用到
		this.columnsX = [];
		for(var i=0;i<columns.length;i++){
			this.columnsX.push(findPosX(columns[i]));
		}
			
	}
	item.onDrag = function(left,top,mouseX,mouseY){
	
		//先要判断在哪一列移动
		var columnIndex = 0; 
		
		for(var i=0;i<this.columnsX.length;i++){
			if((left + this.offsetWidth/2) > this.columnsX[i]){
				columnIndex = i;
			}
		}
		//如果columnIndex在循环中没有被赋值 则表示当前拖动对象在第一列的左边
		//此时也把它放到第一列
		
		var column = columns[columnIndex];
		
		if(this.column != column){
			//之前拖动对象不在这个列
			//将ghost放置到这一列的最下方
			
			column.appendChild(dragGhost);
			this.column = column;
		}
		
		//然后在判断放在这一列的什么位置
		
		var currentNode = null;
		for(var i=0;i<this.column.childNodes.length;i++){
			if(this.column.childNodes[i].className == "item"
			&& this.column.childNodes[i] != this//不能跟拖动元素自己比较 否则不能在本列向下移动
			&& top < findPosY(this.column.childNodes[i])){//从上到下找到第一个比拖动元素的上边距大的元素
			
				currentNode = this.column.childNodes[i];
				break;
			}
		}
		if(currentNode)
			this.column.insertBefore(dragGhost,currentNode);
		else//拖到最下边 没有任何一个元素的上边距比拖动元素的top大 则添加到列的最后
		
			this.column.appendChild(dragGhost);
	}
	item.onDragEnd = function(left,top,mouseX,mouseY){
		this.style.opacity = "1";
		this.style.filter = "alpha(opacity=100)";
		
		this.column.insertBefore(this,dragGhost);
		
		this.style.position = "static";
		this.style.display = "block";
		this.style.width = "auto";
		dragGhost.style.display = "none";
	}
}
        </script>
        <style type="text/css">
			#container{width:800px;}
			.column{width:200px;border:solid 1px #CCCCCC;background:#FCFCFC;padding:0px;float:left;margin:10px;}
			.item{text-align:center;padding:0px;margin:10px;border:solid 1px #CCCCCC;background:white;width:auto;}
			.item h3{margin:0px;height:20px;border-bottom:solid 1px #CCCCCC;background:#CCCCCC;color:white;cursor:move;}
        </style>

这样就可以实现组件的移动了,在上面这段代码中需要引入Drag.js文件,本站提供下载链接,点击下面的下载即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • react组件间的通信

    在使用react过程中,不可避免的需要组件间的数据通信,数据通信一般情况有一下几种情况:

    无邪Z
  • js的函数节流、函数防抖及其使用场景

    先说函数防抖,他的使用场景最多是在搜索时使用,比如百度的搜索,你在输入文字后的一段时间内开始自动搜索而不是每次按下键都执行一次搜索。因为如果每次按键都搜索,则会...

    无邪Z
  • VUE父子组件之间的通信

    在写组件嵌套过程中,必然涉及到父子组件之间的通信问题,父组件向子组件传递很简单,可以通过props来实现。

    无邪Z
  • vue计算属性详解——小白速会

    一、什么是计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如: <div id="exam...

    柴小智
  • 【垂直居中高级篇】你不知道的垂直居中方式

          在Css中对元素进行水平居中是很简单的,如果他是一个行内元素,对它的父元素应用text-align:center;如果是一个块级元素,就对自身应用...

    sam dragon
  • swoole 4.x 连接池协程版本细节坑

    使用swoole 4.x协程版本后,系统资源利用率提高很多,与此同时发现很多开发习惯已经不同

    猿哥
  • 史上最全人工智能进阶干货

    无论是科研院所,商业巨头还是初创企业,各行各业都在大力开发或者引进人工智能,由于储备不足,导致人工智能人才现在出现缺口,而且非常巨大。

    智能算法
  • js中call与apply用法

    前天去面试,有个gg问了一些js知识,其中有一道call与apply用法的题目,尽管在365天前用过call方法,但当时还是没能答上来,今天深入总结一下

    阳光岛主
  • underscore源码解析1

    Math.random()方法返回大于0小于1的一个随机数。 Math.floor()方法执行向下舍入,即它总是将数值向下舍入为最接近的整数。

    Ewall
  • 韩商言为什么让万千少女“上头”?除了颜值,CTF必须了解一下!

    一个是30岁的高冷腹黑霸道总裁,前CTF(网络信息安全竞赛)职业选手,K&K俱乐部老板(CTF方向);

    AiTechYun

扫码关注云+社区

领取腾讯云代金券