最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    正文概述 掘金(头疼脑胀的代码搬运工)   2021-07-08   644

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    这里简单说下实现轻点、长按列表实现错位排序动画实现思路,这里只用到了JQ,没有使用其他的库。胸有成竹、不屑一顾的大神请直接跳到最后点个赞也好,非常感谢。

    用户手势交互可以直接使用mouse事件处理(移动端用touch事件),监听mouse事件在对应dom上的状态。

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画 对于列表item这里采用的className 为menu,当鼠标在列表的item按下时,这里添加一个定时器,定时器延迟操作可以设置长按事件的等待时间。这里记录一下按下时的系统时间。

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    在mouseup事件里再去获取一次系统时间,若两次的时间差小于设置的长按事件界定时长,那么处理轻点事件,若大于该时长,处理长按事件。

    这里就能区分用户操作是轻点还是长按了。

    这里初始化的所有列表位置布局是用JS创建dom对象并添加CSS样式实现的,本人CSS水平有限,没有想到这类场景如何用CSS去添加动画。创建完所有的item后,计算获取每个item对应位置信息这里标为“rect”属性;先创建rect对象,包含四个属性:x,y,width,height。

    获取rect的目的有两个:

    1、是在鼠标移动的过程中去检测当前的even触点位置是否在某个可交换的item上。

    2、判断进行错位动画时获取需要改变后的调整的位置。

    JS动态创建下的dom对象无法改变在文档流中的位置,但是改变后的位置又可能为后续环节使用,所以除了在dom对象上添加了rect属性外,还添加了index属性。这样在排序的过程中,index属性也相应改变,在最后获取排序结果时根据index操作即可。

    上面已经分析了如何执行轻点事件,那么当item在执行轻点事件时候进行移除操作,

    执行移除当前点击的item

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    因为删除了item后面的所有item的index属性都要修改,所以这里添加了一个方法来时现实index的重排。

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    注:参数index是要删除item的索引值。

    依次改变要删除item后面的全部item的rect,并实现错位动画

    修改rect属性 纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    添加错位动画

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    好了,这里就完成了轻点删除及错位动画。

    在遍历所有item前调用了一个排序方法获取以index为排序依据的dom集合!!!

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    这里用到了mousemove方法。

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    1、当拖拽开始后,全局保存下当前的所选的item,获取mouse的even的x值跟y值,控制当前所选的item位置跟随触点变化。

    2、检测触点移动的位置是否处在可交换的其他item上,若条件符合,根据当前的被拖拽的item的与可交换的item的index属性进行判断,修改二者之间的其他item位置,重置其rect及index属性值。

    纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    源码粘出来想看的可以看看,觉得太长的可以忽略,个人随笔,肯定有不严谨的地方,希望大神留言指正,互相学习。

    dragPlus.html

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title></title>
    		<style type="text/css">
    			* {
    				margin: 0;
    				padding: 0;
    			}
    
    			.wrap {
    				width: 380px;
    				height: auto;
    				zoom: 1;
    				overflow: hidden;
    				border: 1px solid #8E8E8E;
    				margin-top: 100px;
    				margin-left: 400px;
    				position: relative;
    			}
    
    			.menu {
    				background-color: darkred;
    				color: #FFFFFF;
    				font-size: 16px;
    				text-align: center;
    				line-height: 30px;
    				position: absolute;
    				display: inline-block;
    				z-index: 10;
    			}
    
    			.active {
    				border: 1px dashed #8E8E8E;
    				position: absolute;
    				display: inline-block;
    				z-index: -1;
    			}
    
    			.onclick {
    				transform: scale(1.2);
    				position: absolute;
    				background-color: darkred;
    				line-height: 30px;
    				height: 30px;
    				width: 70px;
    				text-align: center;
    				color: #FFFFFF;
    			}
    		</style>
    		<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" type="text/javascript"></script>
    		<script src="./dragPlus.js"></script>
    	</head>
    	<body>
    		<div class="wrap" id="wrap"></div>
    	</body>
    	<script>
    		var drag = new DragPlus('wrap', ["测试1", "测试2", "测试3", "测试4", "测试5", "测试1", "测试2", "测试3", "测试4", "测试5", ], 3);
    	</script>
    	<script src="./dragTouchEven.js"></script>
    </html>
    
    

    dragPlus.js

    function DragPlus(vm, items, column) {
    	this.contain = $("#" + vm);
    	this.items = items;
    	this.column = column;
    	this.sep = 10;
    	this.reload();
    	this.duran = 500;
    	this.currentOptionElement = null;
    }
    
    DragPlus.prototype = {
    	//刷新
    	reload: function() {
    		var width = $(this.contain).width();
    		var itemWidth = (width - this.sep * (this.column + 1)) / this.column;
    		var itemHeight = itemWidth;
    		var row = parseInt(this.items.length / this.column) + ((this.items.length % this.column) ? 1 : 0);
    		var maxY = itemHeight * row + this.sep * (row + 1);
    		for (var i = 0; i < this.items.length; i++) {
    			var text = this.items[i];
    			var tempDiv = document.createElement("div");
    			$(tempDiv).attr('class', 'menu')
    			var x = this.sep + (i % this.column) * (itemWidth + this.sep);
    			var y = this.sep + parseInt(i / this.column) * (itemWidth + this.sep);
    			$(tempDiv).css("left", x);
    			$(tempDiv).css("top", y);
    			$(tempDiv).text(text);
    			$(tempDiv).width(itemWidth);
    			$(tempDiv).height(itemHeight);
    			$(this.contain).append(tempDiv);
    			var rect = {}
    			rect.x = x;
    			rect.y = y;
    			rect.width = itemWidth;
    			rect.height = itemHeight;
    			$(tempDiv).attr("rect", JSON.stringify(rect))
    		}
    		$(this.contain).height(maxY)
    		this.resetIndex(null);
    	},
    	//删除
    	deleteItem: function(item) {
    		var index = $(item).attr("index");
    		var rect = $.parseJSON($(item).attr("rect"));
    		this.items.splice(index, 1);
    		$(item).remove()
    		this.resetIndex(index);
    		this.addChangePositionAnimate(index, rect);
    	},
    	//改变位置动画
    	addChangePositionAnimate: function(index, rect) {
    		var items = this.resort();
    		for (var i = items.length - 1; i >= index; i--) {
    			var item = items[i];
    			var newRect = (i == index) ? rect : $.parseJSON($(items[i - 1]).attr("rect"));
    			$(item).attr("rect", JSON.stringify(newRect));
    			this.animate(item, newRect);
    		}
    		var that = this;
    		setTimeout(function() {
    			that.resetParentRect();
    		}, that.duran);
    	},
    	//添加动画
    	animate: function(item, rect) {
    		var that = this;
    		$(item).animate({
    			left: rect.x + 'px',
    			top: rect.y + 'px'
    		}, that.duran);
    	},
    	//重置item索引属性
    	resetIndex: function(index) {
    		if (index == null) {
    			var items = document.getElementsByClassName("menu");
    			for (var i = 0; i < items.length; i++) {
    				var item = items[i];
    				$(item).attr("index", i)
    			}
    		} else {
    			var items = this.resort();
    			for (var i = index; i < items.length; i++) {
    				var item = items[i];
    				var nowIndex = $(item).attr("index");
    				$(item).attr("index", nowIndex - 1);
    			}
    
    		}
    	},
    	//重置父视图高度
    	resetParentRect: function() {
    		if (this.items.length == 0) {
    			$(this.contain).height(this.sep);
    		} else {
    			var width = $(this.contain).width();
    			var itemHeight = (width - this.sep * (this.column + 1)) / this.column;
    			var row = parseInt(this.items.length / this.column) + ((this.items.length % this.column) ? 1 : 0);
    			var maxY = itemHeight * row + this.sep * (row + 1);
    			$(this.contain).height(maxY)
    		}
    	},
    	//创建old占位div
    	createOldPlaceholderElement: function(rect, index) {
    		var tempDiv = document.createElement("div");
    		$(tempDiv).attr('class', 'active')
    		$(tempDiv).attr('id', 'old')
    		var x = rect.x;
    		var y = rect.y;
    		$(tempDiv).css("left", x);
    		$(tempDiv).css("top", y);
    		$(tempDiv).width(rect.width);
    		$(tempDiv).height(rect.height);
    		$(tempDiv).attr("rect", JSON.stringify(rect))
    		$(tempDiv).attr("index", index);
    		$(this.contain).append(tempDiv);
    	},
    	//移动区间模块
    	moveInterval: function(oldElement, newElement) {
    
    		var oIndex = parseInt($(oldElement).attr("index"));
    		var nIndex = parseInt($(newElement).attr("index"));
    
    		//console.log('oIndex=' + oIndex + ',' + 'nIndex=' + nIndex);
    		var rect = $.parseJSON($(newElement).attr("rect"));
    		var oldRect = $.parseJSON($(oldElement).attr("rect"));
    		$(oldElement).css({
    			"left": rect.x,
    			"top": rect.y
    		});
    
    		var items = this.resort();
    
    		if (oIndex < nIndex) {
    			for (var i = nIndex; i > oIndex; i--) {
    				var item = items[i];
    				if (item) {
    					var tempRect = $.parseJSON($(items[i - 1]).attr("rect"))
    					var newRect = (i == oIndex + 1) ? oldRect : tempRect;
    					$(item).attr("rect", JSON.stringify(newRect));
    					var tempIndex = $(items[i - 1]).attr("index");
    					var index = (i == oIndex + 1) ? oIndex : $(items[i - 1]).attr("index");
    					$(item).attr("index", index);
    					this.animate(item, newRect);
    				}
    			}
    		} else {
    			for (var i = nIndex; i < oIndex; i++) {
    				var item = items[i];
    				if (item) {
    					var tempRect = $.parseJSON($(items[i + 1]).attr("rect"))
    					var newRect = (i == oIndex - 1) ? oldRect : tempRect;
    					$(item).attr("rect", JSON.stringify(newRect));
    					var tempIndex = $(items[i + 1]).attr("index");
    					var index = (i == oIndex - 1) ? oIndex : $(items[i + 1]).attr("index");
    					$(item).attr("index", index);
    					this.animate(item, newRect);
    				}
    			}
    		}
    		$(oldElement).attr("rect", JSON.stringify(rect))
    		$(oldElement).attr("index", nIndex);
    		var that = this;
    		$(that.currentOptionElement).attr("rect", JSON.stringify(rect))
    		$(that.currentOptionElement).attr("index", nIndex);
    		setTimeout(function() {
    			that.resetParentRect();
    		}, that.duran + 10);
    	},
    	//重新排序
    	resort: function() {
    		var itemsOld = document.getElementsByClassName("menu");
    		var dic = {};
    		for (var i = 0; i < itemsOld.length; i++) {
    			var item = itemsOld[i];
    			dic[$(item).attr("index")] = item;
    		}
    		var items = [];
    
    		Object.keys(dic).sort().forEach(function(key) {
    			items.push(dic[key]);
    		});
    		return items;
    	}
    }
    
    

    dragTouchEven.js

    $(function() {
    	var action = false; //定义一个全局变量来判断鼠标动作,默认为false
    	var mouseTapX = 0;
    	var mouseTapY = 0;
    	var timer = null;
    	var isLongPress = false;
    	var currentTime = 0;
    	var longpressTime = 500;
    	var animateTime = 500;
    	var currentSelectItem = null;
    	$(document).on("mousedown", ".menu", function(event) { //鼠标按下事件
    		var that = this;
    		currentSelectItem = that;
    		isLongPress = true;
    		drag.currentOptionElement = that;
    		currentTime = Date.parse(new Date());
    		timer = setTimeout(function() {
    			if (isLongPress) {
    				action = true;
    				if ($(".onclick").length < 1) {
    					var left = $(that).offset().left - $(".wrap").offset().left; //获取在wrap内的偏移量
    					var top = $(that).offset().top - $(".wrap").offset().top;
    					mouseTapX = event.pageX - $(that).offset().left;
    					mouseTapY = event.pageY - $(that).offset().top;
    					var rect = $.parseJSON($(that).attr("rect"));
    					var index = $(that).attr("index");
    					drag.createOldPlaceholderElement(rect, index);
    					//$(that).before("<div class='active' id='old'></div>"); //鼠标按下时在原位置创建一个活动的空div
    					$(that).css({
    						"left": left,
    						"top": top,
    					});
    				}
    			}
    		}, longpressTime);
    
    	})
    	$(document).on("mousemove", ".wrap", function(event) { //wrap上的鼠标移动事件,menu 移动
    		if (action == true) {
    			var x = event.pageX - $(".wrap").offset().left; //获取鼠标在wrap的偏移量
    			var y = event.pageY - $(".wrap").offset().top;
    			$(currentSelectItem).css({
    				"left": x - mouseTapX,
    				"top": y - mouseTapY
    			}); //补充内边距
    			judgeInsertLeftOrRight(x, y);
    		}
    	})
    
    	$(document).on("mouseup", function() { //鼠标弹起时将移动的menu 放入新的接受div里,并移除原div位置上的空div
    
    		var nowTime = Date.parse(new Date());
    		isLongPress = (nowTime - currentTime >= longpressTime);
    		if (!isLongPress) {
    			//单点
    			drag.deleteItem(currentSelectItem);
    		} else {
    			//长按
    			var oldElement = $("#old");
    			if ($(oldElement).attr("rect")) {
    				var rect = $.parseJSON($(oldElement).attr("rect"));
    				var oIndex = $(oldElement).attr("index");
    				$(currentSelectItem).attr("rect", JSON.stringify(rect))
    				$(currentSelectItem).attr("index", oIndex);
    				$(currentSelectItem).animate({
    					left: rect.x + 'px',
    					top: rect.y + 'px',
    				}, 200);
    				$("#old").remove();
    			}
    		}
    		action = false;
    	})
    })
    
    function deleteItem(currentSelectItem) {
    	if (currentSelectItem) {
    		drag.deleteItem(currentSelectItem);
    	}
    }
    
    //判断当前的鼠标点的位置在其他标签的位置
    function judgeInsertLeftOrRight(mx, my) {
    	var items = document.getElementsByClassName("menu");
    	for (var i = 0; i < items.length; i++) {
    		var item = items[i];
    		var rect = $.parseJSON($(item).attr("rect"));
    		if (mx > rect.x && mx < rect.x + rect.width && my > rect.y && my < rect.y + rect.height) {
    			insertPlaceholderElement(item);
    			return;
    		}
    	}
    }
    
    //标签前后插入新的占位标签
    function insertPlaceholderElement(item) {
    	drag.moveInterval($("#old"), item);
    }
    
    
            
    
    
    

    起源地下载网 » 纯JS 实现列表轻点删除、长按拖拽及错位排序动画

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元