图片拖拽排序与拖拽删除

转自:https://www.zhangxinxu.com/wordpress/2016/11/html5-drag-drop-module-insert-sort-delete-demo/

代码基于jQuery编写,可以省点事件。另外,兼容性是IE10+以及其他现代浏览器效果OK,不支持IE7-IE9浏览器,因为使用的是原生的HTML5 drag/drop API,一般适合开发一些工具后者内网项目的时候使用。如果对兼容性有要求,大家可以去搜一搜一些复杂的jQuery插件。 


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="description" content="基于HTML5 drag/drop的模块拖动插入排序和删除 » 张鑫旭-鑫空间-鑫生活" />
<meta name="description" content="张鑫旭web前端学习实例页面 基于HTML5 drag/drop的模块拖动插入排序和删除" />
<meta name="keywords" content="web前端, css, jQuery, javascript" />
<meta name="author" content="张鑫旭, zhangxinxu" />
<title>基于HTML5 drag/drop的模块拖动插入排序和删除 » 张鑫旭-鑫空间-鑫生活</title>
<style>
.demo {
	padding-top: 30px;
}
.container {
	background-color: #f0f3f9;
	font-family: 'PingFang SC', 'Microsoft Yahei';
	min-height: 610px;
	position: relative;
	overflow: hidden;
}
.module-ul {
	width: 180px;
	position: absolute; top: 0; bottom: 0; left: 0;
	list-style: none;
	margin: 0;
	padding: 0;
	background-color: #34538b;
}
.module-li {
	margin: 20px auto;
	padding: 10px 0;
	background-color: #fff;
	width: 150px;
	text-align: center;
	cursor: move;
	position: relative;
}
.module-li:hover::before {
	content: '';	
	position: absolute;
	left: 0; right: 0; top: 0; bottom: 0;
	padding: 10px;
	background-color: rgba(0,0,0,.5);
}
.module-body {
	margin-left: 180px;
}
.module-stage {
	max-width: 90%;
	min-width: 600px;
	margin: 0 auto;
}
.module-placeholder {
    height: 584px;
    background-color: #fff;
    position: relative;
	margin: 20px 0;
}
.module-placeholder:empty::before {
    position: absolute;
    left: 50%;
    top: 50%;
	-ms-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    color: #aaa;
    content: '从左侧拖模块放这里';
    font-size: 20px;
}
.module-placeholder.dragenter {
	outline: 2px dashed #ddd;
}

.module-drag {
	padding: 10px 0;
	margin: 20px 0;
	background-color: #fff;
	text-align: center;
	cursor: move;
	position: relative;
}
.module-drag.dragstart {
	opacity: .5;
}
.module-drag:hover::before {
	content: '';
	position: absolute;
	top: 0; left: 0; bottom: 0; right: 0;
}

/* 模块拖拽删除 */
.module-remove {
	position: absolute;
	top: 0; bottom: 0; left: -180px;
	width: 180px;
	padding-top: 40px;
	background-color: #34538b;
	transition: left .25s, background-color .2s;
	z-index: 1;
}
.module-remove.dragenter {
	left: 0;
}
.module-remove-icon {
	position: absolute;
	font-size: 160px;
	left: 50%; top: 0;margin-top: 100px;
	-ms-transform: translate(-50%, -50%);
	transform: translate(-50%, -50%);
	color: #fff;
}
.module-remove:hover,
.module-remove.dragover {
	background-color: #F15656;
}
</style>
</head>

<body>
            
<!-- 演示区域 -->
<div class="container">
	<ul id="module" class="module-ul">	
        <li class="module-li" draggable="true" data-url="https://i0.hippopx.com/photos/320/918/427/sky-clouds-sunlight-dark-preview.jpg">
            <img class="module-img" src="https://i0.hippopx.com/photos/320/918/427/sky-clouds-sunlight-dark-thumb.jpg" height="96" alt="模块占位图1">
        </li>
	    <li class="module-li" draggable="true" data-url="https://i0.hippopx.com/photos/477/768/839/swimmer-sport-swim-water-preview.jpg">
            <img class="module-img" src="https://i0.hippopx.com/photos/477/768/839/swimmer-sport-swim-water-thumb.jpg" height="128" alt="模块占位图2">
        </li>
        <li class="module-li" draggable="true" data-url="https://i0.hippopx.com/photos/20/987/594/woman-young-rain-pond-preview.jpg">
            <img class="module-img" src="https://i0.hippopx.com/photos/20/987/594/woman-young-rain-pond-thumb.jpg" height="96" alt="模块占位图3">
        </li>
        <li class="module-li" draggable="true" data-url="https://i0.hippopx.com/photos/740/837/204/spices-cinnamon-sticks-odor-aroma-preview.jpg">
            <img class="module-img" src="https://i0.hippopx.com/photos/740/837/204/spices-cinnamon-sticks-odor-aroma-thumb.jpg" height="86" alt="模块占位图4">
        </li>
	</ul>
    <div id="moduleRemove" class="module-remove"><span class="module-remove-icon">×</span></div>
    <div id="moduleBody" class="module-body">
    	<div id="moduleStage" class="module-stage">
        	<div id="modulePlaHd" class="module-placeholder"></div>
        </div>
    </div>
</div>
<!-- 演示区域 结束 -->


<script src="http://apps.bdimg.com/libs/jquery/1.9.0/jquery.min.js"></script>
<script>
var moduleDrag = (function() {
	// 模块操作类名,标记用
	var CL_MODULE = 'jsDragModule';
	// 状态类名
	var CL_DRAGENTER = 'dragenter';
	var CL_DRAGOVER = 'dragover';
	var CL_DRAGSTART = 'dragstart';
	
	return  {
		el: {},
		store: {},
		events: function() {
			var self = this;
			// 拖拽相关的事件
			var el = self.el;
			// 元素
			var module = el.module, stage = el.stage;
			// 拖拽模块
			var modlder = el.modlder;
			
			var lis = module.find('li'), elDrag = null;

			// 左侧拖拽
			module.delegate('li', {
				dragstart: function(event) {
					var li = $(this);
					// 标记当前拖拽元素
			        elDrag = li;
					event.originalEvent.dataTransfer.setData('text/plain', 'for firefox');
				},
				dragend: function(event) {
					// 拖拽结束
			        elDrag = null;
					event.preventDefault();
				}
			});

			// 经过占位模块元素
			modlder.on({
				dragover: function(event) {
					event.preventDefault();
				},
				dragenter: function() {
					modlder.addClass(CL_DRAGENTER);
				},
				drop: function(event) {
					var url = elDrag && elDrag.attr('data-url');
					if (url) {
						// 从左侧拖动到主内容区域时候放下的回调
						// 在本例子中,就是插入大图
						modlder.empty().hide();
						// 在占位符元素的前面插入模块
						self.insertModule('<img src="'+ url +'" height="'+ (elDrag.find('img').height() * 4) +'">', modlder, 'before');
					}
					modlder.removeClass(CL_DRAGENTER);
					
					event.preventDefault();
				}
			});

			// 模块响应左侧的拖拽以及其他模块的拖拽
			var body = el.body;

			// 实时记录鼠标的位置,方便判断鼠标当前在鼠标的上半区还是下半区
			var pos = {};
			document.addEventListener("dragover", function(event){
			    pos.y = event.pageY;
			}, false);

			body.delegate('.' + CL_MODULE, {
				dragover: function(event) {
					// 触发的节奏是:歘歘歘
					var current = $(this);
					// 1. 求得模块的水平中心位置
					var centerY = current.offset().top + current.height() * 0.5;

					if (typeof pos.y != 'number' || this == elDrag[0]) {
						return;
					}

					if (!elDrag) {
						return;
					}
					// 上半区还是下半区
					if (pos.y <= centerY) {
						// 上
						// 如果拖拽的是li元素,认为是左侧列表
						if (elDrag.is('li')) {
							modlder.show().insertBefore(current);
						} else if (elDrag.hasClass(CL_MODULE)) {
							var prev = current.prev();
							if (prev.length && prev.hasClass(CL_MODULE)) {
								if (prev[0] !== elDrag[0]) {
									elDrag.insertBefore(current);
								}
							} else {
								elDrag.insertBefore(current);
							}				
						}
					} else {
						if (elDrag.is('li')) {
							modlder.show().insertAfter(current);
						} else if (elDrag.hasClass(CL_MODULE)) {
							// 当拖拽位置在下半区的时候
							// 同时,拖拽元素不是检测元素的下一个的时候
							// 执行位置调整
							var next = current.next();
							// 如果后面没元素,或者元素不是模块元素
							if (next.length && next.hasClass(CL_MODULE)) {
								if (next[0] !== elDrag[0]) {
									// 如果后面的元素不是拖动的元素,位置变化
									elDrag.insertAfter(current);
								}
							} else {
								elDrag.insertAfter(current);
							}
						}
					}
					event.preventDefault();
				},
				dragenter: function(event) {
					// 触发的节奏是: 歘  歘  歘
					event.preventDefault();
				},
				// 模块间的拖来拖去
				dragstart: function(event) {
					elDrag = $(this).addClass(CL_DRAGSTART);

					// 右侧删除
					el.remove.addClass(CL_DRAGENTER);
					
					event.originalEvent.dataTransfer.setData('text/plain', 'for firefox');
				},
				dragend: function(event) {
					/*拖拽结束*/
					$(this).removeClass(CL_DRAGSTART);
					elDrag = null;

					// 右侧删除
					el.remove.removeClass(CL_DRAGENTER);
					
					event.preventDefault();
				}
			});
			
			// 拖动到删除元素时候
			el.remove.on({
				dragenter: function() {
					$(this).addClass(CL_DRAGOVER);
				},
				dragover: function(event) {
					event.preventDefault();
				},
				dragout: function() {
					$(this).removeClass(CL_DRAGOVER);
				},
				drop: function(event) {
					// 删除
					if (elDrag && elDrag.hasClass(CL_MODULE)) {
						var id = elDrag.attr('id');
						if (id) {
							// 删除该模块存储数据
							delete self.store[id];
						}
						
						elDrag.remove();

						if ($('.' + CL_MODULE).length == 0) {
							modlder.show();
						}
					}

					// 功成身退
					$(this).removeClass(CL_DRAGENTER).removeClass(CL_DRAGOVER);
					
					event.preventDefault();
				}
			});
		},
		
		insertModule: function(html) {
			var self = this;
			// 创建随机id
			var id = ('id_' + Math.random()).replace('0.', '');
			//  给模块HTML穿上一件可拖拽的外衣
			var htmlWrap = '<div id="'+ id +'" class="'+ CL_MODULE +' module-drag" draggable="true">'
			+ html
			+ '</div>';

			// 缓存颜色
			var module = $(htmlWrap);

			// 是否已经有过此模块
			var isModuled = false;
			$.each(self.store, function(id, obj) {
				// 如果HTML内容一样,认为是同一模块
				if (obj && obj.html && obj.html == html) {
					isModuled = true;
					return false;
				}
			});

			if (isModuled && window.console) {
				alert('此模块已经被选择');
				return self;
			}
			
			// 存储
			self.store[id] = {
				html: html
			};
			
			// 占位符前面插入内容
			self.el.modlder.before(module);

			return self;
		},
		
		init: function() {
			var self = this;

			// 一些元素
			self.el = $.extend(self.el, {
				module: $('#module'),
				remove: $('#moduleRemove'),
				body: $('#moduleBody'),
				stage: $('#moduleStage'),
				modlder: $('#modulePlaHd')
			});
			
			self.events();
		}
	};	
})();

moduleDrag.init();
</script>

</body>
</html>

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值