直接进入主题,先看一下效果图
大概就是这样的一个效果,这样的效果在iOS上很常见,本人就是做iOS开发,iOS上面的UITableView 在系统框架上是会提供这样的用户操作API的。
在web中同样也想实现这样的用户操作应该怎么做?这里简单的说一下思路,大神、大佬,凡是“大”字辈儿的觉得“班门弄斧”的可以最后点个赞,非常感谢。
封装对象,监管所有的用户操作
对象初始化方法
对象初始化
这里创建了一个dragMoreOption对象,顾名思义就是拖拽展示更多用户操作。
参数说明
vm:父类容器id;
cellClassName:子类做侧滑dom对象的class;
items:需要展示自定义内容及其他配置项,这里只添加了一个背景颜色值;
给对象添加 initTouchEven 方法,实现鼠标的mousedown、mousemove、mouseup方法
步骤一、给全部的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全部宽度的一半时抬起鼠标自动打开,小于一半时抬起鼠标自动恢复原状。
最后直接上代码,思路总是次要的,代码诚不欺我
目录结构
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属性。
好了,代码都是自己手敲的,要多简朴有多简朴,大家多担待,互相学习,共同进步。