纯JS实现列表侧滑展示更多操作按钮及点击事件

963 阅读4分钟

直接进入主题,先看一下效果图

屏幕录制2021-07-09下午3.26.11-迅捷PDF转换器.gif

点击事件.gif

大概就是这样的一个效果,这样的效果在iOS上很常见,本人就是做iOS开发,iOS上面的UITableView 在系统框架上是会提供这样的用户操作API的。

在web中同样也想实现这样的用户操作应该怎么做?这里简单的说一下思路,大神、大佬,凡是“大”字辈儿的觉得“班门弄斧”的可以最后点个赞,非常感谢。

封装对象,监管所有的用户操作

对象初始化方法 image.png

对象初始化 image.png

这里创建了一个dragMoreOption对象,顾名思义就是拖拽展示更多用户操作。

参数说明

vm:父类容器id;

cellClassName:子类做侧滑dom对象的class;

items:需要展示自定义内容及其他配置项,这里只添加了一个背景颜色值;

给对象添加 initTouchEven 方法,实现鼠标的mousedown、mousemove、mouseup方法

image.png

步骤一、给全部的cell(这里指需要侧滑操作的dom对象,iOS下称为cell,细胞的意思)添加mousedown方法,获取当前鼠标点击的初始位置(这里用一个自定义point的对象保存,保存evenX,evenY),这之所以个cell添加mousedown事件是要获取并全局保存一下当前的cell。

步骤二、给最外层的父节点添加拖拽mousemove事件,这里由于进行侧滑手势,所以只需要处理当前even.x值即可。当然,这里也用自定义point对象保存了一下移动中的even.x和even.y,由于只要求左滑,那么就处理移动过程点的x值小于一开始的mousedown记录点的x值即可,获取二者的差值,修改当前全局保存的cell的css中的left值。

步骤三、给每个cell添加可操作的item(dom对象)块,index(索引)及expend(是否展开的标示)。

步骤四、当cell处于展开的位置时,将它对应的可操作的item的'z-index'值设置到cell的上面。当cell处于收起状态时可操作的item的'z-index'值设置到cell的下面。这样就为可操作的item添加了点击事件而不会cellmousedown事件有冲突。

步骤五、简单处理一下手势滑动的位置判定,超过可展示item全部宽度的一半时抬起鼠标自动打开,小于一半时抬起鼠标自动恢复原状。

最后直接上代码,思路总是次要的,代码诚不欺我

目录结构

image.png

dragMoreOption.html


<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			
			.wrap {
				width: 380px;
				height: 400px;
				zoom: 1;
				overflow-x: scroll;
				overflow-y: hidden;
				border: 1px solid #8E8E8E;
				margin-top: 100px;
				margin-left: 400px;
				position: relative;
			}
			.cell {
				width: 100%;
				height: 45px;
				border-bottom: #8E8E8E solid 1px;
				background-color: lightgray;
				position: relative;
			}
		</style>
		<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" type="text/javascript"></script>
		<script src="dragMoreOption.js"></script>
	</head>
	<body>
		<div class="wrap" id="wrap">
			<div class="cell">测试1</div>
			<div class="cell">测试2</div>
			<div class="cell">测试3</div>
		</div>
		<script>
			var dragMoreOption = new DragMoreOption('wrap', 'cell',
				[{
					'title': '删除',
					'color': 'red'
				}, {
					'title': '编辑',
					'color': 'green'
				}]);
		</script>
	</body>
</html>

dragMoreOption.js

function DragMoreOption(vm, cellClassName, items) {
	this.contain = $("#" + vm);
	this.vmName = vm;
	this.containWidth = $(this.contain).width();
	this.cellClassName = cellClassName;
	this.items = items;
	this.action = false; //定义一个全局变量来判断鼠标动作,默认为false
	this.mouseTapX = 0;
	this.mouseTapY = 0;
	this.currentSelectItem = null;
	this.beginPoint = {};
	this.moveX = null;
	this.itemBtnWidth = 80;
	this.isBounceActive = false;
	this.bounceInterval = 300; //弹簧效果时长
	this.totleWidth = this.itemBtnWidth * this.items.length;
	this.isHaveExpend = false;
	this.isOptionSameItem = false;
	this.initTouchEven();
	this.addCellPrototype();
	
}

DragMoreOption.prototype = {
	//初始化touchEven
	initTouchEven: function() {
		var that = this;
		$(document).on("mousedown", "." + that.cellClassName, function(event) {
			//鼠标按下事件
			that.action = true;
			that.isOptionSameItem = (this == that.currentSelectItem);
			that.beginPoint.x = event.pageX;
			that.beginPoint.y = event.pageY;
			that.moveX = 0;
			if(that.isHaveExpend){
				that.optionItemBeforeOrBelow(false);
				$(that.currentSelectItem).animate({
					left: 0 + 'px',
				}, that.bounceInterval);
			}
			that.currentSelectItem = this;
			
		})
		$(document).on("mousemove", "." + that.vmName, function(event) {
			//wrap上的鼠标移动事件,menu 移动
			if (that.action == true && !that.isBounceActive && !that.isOptionSameItem) {

				var currentPoint = {};
				currentPoint.x = event.pageX;
				currentPoint.y = event.pageY;
				var changeX = currentPoint.x - that.beginPoint.x;
				if (Math.abs(changeX) > that.totleWidth) {
					changeX = -(that.totleWidth);
				}
				that.moveX = Math.abs(changeX);
				if (changeX < 0) {
					$(that.currentSelectItem).css({
						"left": changeX + 'px',
					});
				}
			}
		})

		$(document).on("mouseup", function() {
			//鼠标弹起时将移动的menu 放入新的接受div里,并移除原div位置上的空div
			that.isBounceActive = true;
			var isNeedExpend = that.moveX > (that.totleWidth) / 2.0
			if (!isNeedExpend) {
				$(that.currentSelectItem).animate({
					left: 0 + 'px',
				}, that.bounceInterval);
			} else {
				$(that.currentSelectItem).animate({
					left: - that.totleWidth + 'px',
				}, that.bounceInterval);
			}
			setTimeout(function() {
				that.isBounceActive = false;
				$(that.currentSelectItem).attr("expend", isNeedExpend);
				that.isHaveExpend = isNeedExpend;
				if(!isNeedExpend) {
					that.currentSelectItem = null;
				} else {
					that.optionItemBeforeOrBelow(true);
				}
			}, that.bounceInterval + 10);
			that.action = false;
		})
	},
	//添加cell index(索引)、expend(是否为操作状态)属性
	addCellPrototype: function() {
		var items = document.getElementsByClassName(this.cellClassName);
		var that = this;
		for (var i = 0; i < items.length; i++) {
			var item = items[i];
			$(item).attr("index", i);
			$(item).attr("expend", false);
			for(var j = 0;j < this.items.length;j++){
				//添加操作选项
				var cellObj = this.items[j];
				var y = $(item).offset().top - $(this.contain).offset().top;
				var tempDiv = document.createElement("div");
				$(tempDiv).css("left", this.containWidth - this.itemBtnWidth * (j + 1));
				$(tempDiv).css("top", y-1);
				$(tempDiv).css("width", this.itemBtnWidth);
				$(tempDiv).css("height", $(item).height() + 1 + 'px');
				$(tempDiv).css("position", 'absolute');
				$(tempDiv).css("text-align", 'center');
				$(tempDiv).css("display", 'inline-block');
				$(tempDiv).css("background-color", cellObj.color);
				$(tempDiv).css("lineHeight", $(item).height() + 1 + 'px');
				$(tempDiv).css("z-index", '-1');
				$(tempDiv).css("color", 'white');
				$(tempDiv).attr('class', 'itemStyle')
				$(tempDiv).text(cellObj.title);
				var indexPath = {'row':i,'column':j};
				$(tempDiv).attr("indexPath", JSON.stringify(indexPath))
				$(this.contain).append(tempDiv);
				$(tempDiv).click(function(){
				  that.optionItemClickEven($.parseJSON($(this).attr("indexPath")));
				});
			}
		}
	},
	//添加item点击事件
	optionItemClickEven:function(indexPath){
		var title = this.items[indexPath.column].title;
		alert('你点击了' + title);
	},
	//展开后将可操作的item移到最上层或最下层
	optionItemBeforeOrBelow:function(isUp){
		var index = $(this.currentSelectItem).attr('index');
		var items = document.getElementsByClassName('itemStyle');
		for(var i = 0;i < items.length;i++){
			var item = items[i];
			var indexPath = $.parseJSON($(item).attr("indexPath"));
			if(indexPath.row == index){
				$(item).css("z-index", isUp ? '10' : '-1');
			}
		}
	}
}

这里代码里有些细节,比如如何确定点击的item的位置代码中是有处理的,就是为cell添加index属性,给每个item添加indexPath属性。

好了,代码都是自己手敲的,要多简朴有多简朴,大家多担待,互相学习,共同进步。