拖拽

拖拽原理:

● 当鼠标在盒子上按下的时候,我们开始拖拽

◆ 记录鼠标按下的位置;

◆ 元素当前位置(左上角)

◆ 给元素绑定onmousemoveonmouseup事件

● 当鼠标移动的时候,计算盒子的最新位置(左上角位置)

◆ 考虑边界值问题

● 当鼠标抬起的时候说明拖拽结束,把onmousemove和onmouseup方法移除

 

注意:鼠标焦点丢失问题

● 鼠标焦点丢失:当鼠标移动过快的时候,鼠标会脱离盒子,导致盒子的mouseup和mousemove事件都移除不掉

◆ 在ie和ff中,用一个方法(setCapture()和releaseCapture())把盒子和鼠标绑定在一起即可

◆ 但是这个方法在chrome下不兼容:解决:我们把mousemove/mouseup绑定给document,此时出现新的问题,事件绑定给document后this指向出问题,要用call重新指向


1.鼠标拖拽

例1:拖拽

var box = document.getElementById("box");
box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight) - box.offsetHeight)/2 +"px";
box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 +"px";
box.onmousedown = down;
 
function down(e){
e = e || window.event;
// 记录鼠标开始位置
this["strX"] = e.clientX;
this["strY"] = e.clientY;
// 记录元素左上角位置
this["strL"] = parseFloat(this.style.left);
this["strT"] = parseFloat(this.style.top);
 
// 给元素绑定移动和抬起事件
this.onmousemove = move;
this.onmouseup = up;
}
function move(e){
e = e || window.event;
 
// 当前元素的位置
var curL = (e.clientX - this["strX"]) + this["strL"];
var curT = (e.clientY - this["strY"]) + this["strT"];
// 边界判断
var minL = 0,minT = 0,
maxL = (document.documentElement.clientWidth || document.body.clientWidth)- this.offsetWidth,
maxT = (document.documentElement.clientHeight ||document.body.clientHeight) - this.offsetHeight;

curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
this.style.left = curL + "px";
this.style.top = curT + "px";
}
function up(e){
this.onmousemove = null;
this.onmouseup = null;
}

例2:优化-解决鼠标焦点丢失问题

var box = document.getElementById("box");
box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight) - box.offsetHeight)/2 +"px";
box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 +"px";
box.onmousedown = down; 
 
function down(e){
e = e || window.event;
// 记录鼠标开始位置
this["strX"] = e.clientX;
this["strY"] = e.clientY;
// 记录元素左上角位置
this["strL"] = parseFloat(this.style.left);
this["strT"] = parseFloat(this.style.top);
 
// 给元素绑定移动和抬起事件
if(this.setCapture){//(ie/ff支持)
this.setCapture();//把当前鼠标和this绑定在一起
this.onmousemove = move;
this.onmouseup = up;
} else {
// 这样绑定的话,move和up中的this都变为了document
// document.onmousemove = move;
// document.onmouseup = up;
 
var _this = this;
document.onmousemove = function(e){
e = e || window.event;
move.call(_this,e);
}
document.onmouseup = function(e){
e = e || window.event;
up.call(_this,e);
}
}

function move(e){
e = e || window.event;
 
// 当前元素的位置
var curL = (e.clientX - this["strX"]) + this["strL"];
var curT = (e.clientY - this["strY"]) + this["strT"];
 
// 边界判断
var minL = 0,minT = 0,
maxL = (document.documentElement.clientWidth || document.body.clientWidth)   - this.offsetWidth,
maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight;
curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
 
this.style.left = curL + "px";
this.style.top = curT + "px";
}
function up(e){
if(this.releaseCapture){//把当前鼠标和this解绑(ie/ff支持)
this.releaseCapture();
this.onmousemove = null;
this.onmouseup = null;
} else {
document.onmousemove = null;
document.onmouseup = null;
}
}

2.触摸拖拽

在移动端触屏事件有四个

// 手势事件

touchstart  //当手指接触屏幕时触发

touchmove   //当已经接触屏幕的手指开始移动后触发

touchend    //当手指离开屏幕时触发

touchcancel事件

每个触摸事件对象中都包括了touches这个属性,用于描述前位于屏幕上的所有手指的一个列表

e.touches确实能保留所有触发点的事件对象

e.touches.length 的长度是手指的触点的个数

e.traget 获取的是当前的元素对象

touches//是当前屏幕上所有触摸点的列表;
targetTouches //是当前对象上所有触摸点的列表;
changedTouches //是涉及当前事件的触摸点的列表。

注意:

touchend 事件中得到的是一个touches的最终值,也就是delete后的列表,所以获取到的touches.length已经减少了,相当于--touches的处理后结果

touches[0] 并不能获取到当前的指向的手势,因为是一个列表,不能确定是哪个一个引用

 

例:拖拽实例

var box = document.getElementById("box");
box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight) - box.offsetHeight)/2 +"px";
box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 +"px";
 
box.addEventListener('touchstart',down,false);
box.ontouchstart = touchStart;
function touchStart(e){
e = e || window.event;
if(e.touches.length){
e.preventDefault();//防止滑屏
var touch = e.targetTouches [0];

this["strX"] = touch.pageX;
this["strY"] = touch.pageY;
this["strL"] = parseFloat(this.style.left);
this["strT"] = parseFloat(this.style.top);
 
this.ontouchmove = touchMove;
this.ontouchend = touchEnd;
}
}
function touchMove(e){
e = e || window.event;
e.preventDefault();
var touch = e.targetTouches [0];

var curL = touch.pageX - this["strX"] + this["strL"];
var curT = touch.pageY - this["strY"] + this["strT"];
 
var minL = 0,minT = 0,
maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth,
maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight;

curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
 
this.style.left = curL + "px";
this.style.top = curT + "px";
}
function touchEnd(e){
this.ontouchmove = null;
this.ontouchend = null;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,针对您的问题,我理解您想实现在 Android 应用中,用户可以通过长按某个元素并拖动,实现多张图片的拖拽和拖放。我可以为您提供以下思路和代码示例: 首先,您需要为每一张图片设置一个触摸事件,以便用户可以通过长按并拖动图片。例如,在您的布局文件中,可以为每个图片添加如下代码: ```xml <ImageView android:id="@+id/image1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/image1" android:tag="draggable" android:longClickable="true" android:onLongClick="onLongClickImage" /> ``` 其中,`android:tag="draggable"` 表示该元素可以被拖拽,`android:longClickable="true"` 表示该元素可以被长按,`android:onLongClick="onLongClickImage"` 表示当用户长按该元素时,会调用 `onLongClickImage` 方法。 接下来,您需要实现 `onLongClickImage` 方法,以便能够在用户长按图片时启动拖拽事件。例如,可以使用 `View.OnLongClickListener` 接口来实现该方法: ```java public class MainActivity extends AppCompatActivity implements View.OnLongClickListener { private ImageView mSelectedImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 为每个图片添加长按事件 findViewById(R.id.image1).setOnLongClickListener(this); findViewById(R.id.image2).setOnLongClickListener(this); findViewById(R.id.image3).setOnLongClickListener(this); } @Override public boolean onLongClick(View v) { // 记录选中的图片 mSelectedImage = (ImageView) v; // 启动拖拽事件 View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); v.startDragAndDrop(null, shadowBuilder, null, 0); return true; } } ``` 在这个例子中,当用户长按某个图片时,会记录选中的图片并启动拖拽事件。拖拽事件使用 `View.startDragAndDrop` 方法来启动,并使用 `View.DragShadowBuilder` 创建一个拖拽的阴影。 最后,您需要实现 `View.OnDragListener` 接口来处理拖拽事件。例如,可以使用以下代码来实现: ```java public class MainActivity extends AppCompatActivity implements View.OnLongClickListener, View.OnDragListener { private ImageView mSelectedImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 为每个图片添加长按事件 findViewById(R.id.image1).setOnLongClickListener(this); findViewById(R.id.image2).setOnLongClickListener(this); findViewById(R.id.image3).setOnLongClickListener(this); // 设置拖拽事件 findViewById(R.id.container).setOnDragListener(this); } @Override public boolean onLongClick(View v) { // 记录选中的图片 mSelectedImage = (ImageView) v; // 启动拖拽事件 View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); v.startDragAndDrop(null, shadowBuilder, null, 0); return true; } @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: // 拖拽事件开始,返回 true 表示可以接收拖拽事件 return true; case DragEvent.ACTION_DRAG_ENTERED: // 拖拽事件进入容器,改变容器的背景色 v.setBackgroundColor(Color.YELLOW); break; case DragEvent.ACTION_DRAG_EXITED: // 拖拽事件离开容器,恢复容器的背景色 v.setBackgroundColor(Color.TRANSPARENT); break; case DragEvent.ACTION_DROP: // 拖拽事件释放,将图片从原位置移动到容器中 ViewGroup viewGroup = (ViewGroup) mSelectedImage.getParent(); viewGroup.removeView(mSelectedImage); ((ViewGroup) v).addView(mSelectedImage); break; case DragEvent.ACTION_DRAG_ENDED: // 拖拽事件结束,恢复容器的背景色 v.setBackgroundColor(Color.TRANSPARENT); break; } return true; } } ``` 在这个例子中,当用户将图片拖拽到容器中时,会将图片从原位置移动到容器中。您可以根据需要修改代码,实现更复杂的拖拽和拖放功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值