一、拖拽效果
分析:
1.拖拽效果必须鼠标按下(mousedown),切鼠标移动(mousemove )执行代码,鼠标弹起(mouseup)解除事件
2.鼠标的坐标减去 鼠标在盒子内的坐标, 才是拖拽目标真正要移动的位置
3.鼠标移动和弹起事件如果加给小盒子,那么在快速移动鼠标的时候会无法解绑事件,所以为了用户体验度,把这两个事件加给文档(document)
4.判断物体移动边界,小盒子最大移动距离=父元素(这里用当前窗口位置)-小盒子的宽高,然后分别判断他们最大的移动距离,针对边界值分别进行处理
5.如果拖拽目标是img,要阻止浏览器的默认行为,这里用return false;发现不兼容IE低版本,利用全局捕获解决(setCapture)
6.检测碰撞:
- 这里的思路是,找出拖拽目标移动的安全区,然后利用反证的思想,对碰撞区作处理
- 红色的盒子是拖拽目标,绿色盒子是碰撞区,其余者为安装区
- 如果L1的值大于R2的值那么拖拽目标就处于安全区,
- 如果T1的值大于B2的值那么拖拽目标就处于安全区,依此类推,可以找出安全区范围,利用if()else()语句,else就是碰撞区
css代码
<style>
* {
padding: 0;
margin: 0;
}
#box {
width: 150px;
height: 150px;
background: red;
position: absolute;
}
#two {
width: 200px;
height: 200px;
background: green;
position: absolute;
top: 200px;
left: 600px;
}
<body>
<div id="box"></div>
<div id="two"></div>
</body>
js部分
<script>
var o = document.getElementById('box');//移动的物体
var box = document.getElementById('two');//被碰撞物体
var vH = document.documentElement.clientHeight;//视图的高度
var vW = document.documentElement.clientWidth;//视图的宽度
//添加鼠标按下事件
o.onmousedown = function (e) {
e = e || window.event;
//鼠标距离物体的相对位置(left,top)
var disX = e.clientX - this.offsetLeft,
disY = e.clientY - this.offsetTop;
//计算被碰撞物体的位置
var L2 = box.offsetLeft,
T2 = box.offsetTop,
R2 = L2 + box.offsetWidth,
B2 = T2 + box.offsetHeight;
//判断,若是在低版本IE上,为物体添加全局捕获
if (o.setCapture) {
o.setCapture();
}
//鼠标移动
document.onmousemove = function (e) {
e = e || window.event;
var x = e.clientX - disX;//物体位置=鼠标的位置-鼠标相对于物体的位置
var y = e.clientY - disY;//物体位置
//判断边界问题
if (x < 0) {
x = 0;//最左边
} else if (x > vW - o.offsetWidth) {
x = vW - o.offsetWidth;//最右边
}
if (y < 0) {
y = 0;//最上边
} else if (y > vH - o.offsetHeight) {
y = vH - o.offsetHeight;
}
//计算碰撞逻辑中,移动物体的位置
var L1 = x,
T1 = y,
R1 = L1 + o.offsetWidth,
B1 = T1 + o.offsetHeight;
//判断碰撞
if (L1 > R2 || T1 > B2 || R1 < L2 || B1 < T2) {
box.style.background = 'green';
} else { //碰撞区域
box.style.background = "orange";
}
//在鼠标移动过程中,修改物体的位置
o.style.left = x + "px";
o.style.top = y + 'px';
};
//鼠标抬起
document.onmouseup = function () {
// console.log('up');
document.onmousemove = null;
document.onmouseup = null;
//释放全局捕获
if (o.releaseCapture) {
o.releaseCapture();
}
};
return false;//拦截浏览器的默认行为
};
</script>
二、动画函数的封装
核心原理,通过定时器不断改变目标对象属性的值
核心公式:
步长(速度)=(目标位置-当前位置)/10(系数,为了改变透明度这里用100)
speed = (target - cur) / 100;
//获取样式 解决getComputedStyle的兼容问题
function getStyle(obj, attr) {
if (getComputedStyle) { //标准浏览器
return getComputedStyle(obj, null)[attr];
}
return obj.currentStyle[attr]; //IE8之下
}
//obj目标对象,attr要改变的属性,target目标位置
function move(obj, attr, target) {
//执行之前先清除上一次的定时器
clearInterval(obj.timer);
//启动定时器,为对象新增属性timer,用来保存定时器编号
obj.timer = setInterval(function() {
var cur = getStyle(obj, attr); //动画执行时,每一次的最新值
var speed; //速度
if (attr == 'opacity') {
speed = (target - cur) / 100; //放大速度系数 100
} else {
cur = parseInt(cur); //当前位置
speed = (target - cur) / 10; //速度
//速度小于0,向左移动,向下取整才可以;速度大于0,向右移动,向上取整
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //最后的时候,速度小于1,向上取整1
}
//到达目标位置停止的定时器
if (cur == target) {
clearInterval(t);
}
if (attr == "opacity") { //修改透明度
obj.style.opacity = parseFloat(cur) + speed;
} else {
obj.style[attr] = cur + speed + "px";
}
}, 30);
}