拖拽
<style>
div {
width: 100px;
height: 100px;
background: deeppink;
position: absolute;
left: 50px;
top: 50px;
}
</style>
</head>
<body>
<div>我和你心连心</div>
<script>
var div = document.getElementsByTagName('div')[0];
div.onmousedown = function (e) {//按下
e = e || window.event;
var w = e.clientX - div.offsetLeft;
var h = e.clientY - div.offsetTop;
//鼠标相对于div的位置
var maxLeft = document.documentElement.clientWidth - this.offsetWidth;
var maxTop = document.documentElement.clientHeight - this.offsetHeight;
//计算最大边界
if (this.setCapture) {
this.setCapture();//全局捕获只有在IE低版本中有效
}
document.onmousemove = function (e) {//移动
e = e || window.event;
left = e.clientX - w;
topa = e.clientY - h;
//div相对于body的位置
console.log(left, topa);
if (left <= 0) {
left = 0;
} else if (left >= maxLeft) {
left = maxLeft;
}
if (topa <= 0) {
topa = 0;
} else if (topa >= maxTop) {
topa = maxTop;
}
div.style.left = left + 'px';
div.style.top = topa + 'px';
console.log(left, topa);
return false;//拦截浏览器默认行为 拖拽文字或图片
}
document.onmouseup = function () {//抬起
document.onmouseup = null;
document.onmousemove = null;
if (div.releaseCapture) {
div.releaseCapture();//释放全局捕获
}
}
}
</script>
</body>
全局捕获
- setCapture方法给元素添加全局捕获,元素只要添加了全局捕获会一直监听对应的事件,只要发现有对应的事件触发,就会截获事件,由添加了全局捕获的元素去处理,全局捕获使用完了以后,通过releaseCapture释放捕获。
<body>
<button>按钮1</button>
<button>按钮2</button>
<script>
var btn = document.getElementsByTagName('button');
btn[0].onclick = function(){
console.log(1);
}
btn[1].onclick = function(){
console.log(2);
}
btn[0].setCapture();//全局捕获,仅在IE低版本中生效
</script>
</body>
多物体运动
<style>
div {
width: 100px;
height: 100px;
background: deeppink;
position: absolute;
left: 50px;
top: 50px;
}
</style>
</head>
<body>
<div style="background: red;left: 0;"></div>
<div style="background: skyblue;left: 100px;"></div>
<div style="background: lightcoral;left: 200px;"></div>
<div style="background: yellowgreen;left: 300px;"></div>
<script>
var div = document.getElementsByTagName('div');
for(var i = 0;i < div.length;i++){
run(div[i])
}
function run(obj){
obj.onmousedown = function (e) {//按下
e = e || window.event;
var w = e.clientX - obj.offsetLeft;
var h = e.clientY - obj.offsetTop;
//鼠标相对于div的位置
var maxLeft = document.documentElement.clientWidth - this.offsetWidth;
var maxTop = document.documentElement.clientHeight - this.offsetHeight;
//计算最大边界
if (this.setCapture) {
this.setCapture();//全局捕获只有在IE低版本中有效
}
document.onmousemove = function (e) {//移动
e = e || window.event;
left = e.clientX - w;
topa = e.clientY - h;
//div相对于body的位置
console.log(left, topa);
if (left <= 0) {
left = 0;
} else if (left >= maxLeft) {
left = maxLeft;
}
if (topa <= 0) {
topa = 0;
} else if (topa >= maxTop) {
topa = maxTop;
}
obj.style.left = left + 'px';
obj.style.top = topa + 'px';
return false;//拦截浏览器默认行为 拖拽文字或图片
}
document.onmouseup = function () {//抬起
document.onmouseup = null;
document.onmousemove = null;
if (obj.releaseCapture) {
obj.releaseCapture();//释放全局捕获
}
}
}
}
</script>
</body>
碰撞检测
<style>
#one {
width: 100px;
height: 100px;
background: red;
position: absolute;
}
#two {
width: 200px;
height: 200px;
background: blue;
position: absolute;
left: 550px;
top: 200px;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
<script>
var one = document.getElementById('one');
var two = document.getElementById('two');
one.onmousedown = function(e){
e = e || window.event;
var w = e.clientX - this.offsetLeft;
var h = e.clientY - this.offsetTop;
//获取鼠标相对于div的位置
var shang = two.offsetTop,
zuo = two.offsetLeft,
xia = shang + two.offsetHeight,
you = zuo + two.offsetWidth;
//计算中心物体的四个边界
//左右边界到最左边的距离,上下边界到最上面的距离
if(this.setCaptrue){
this.setCaptrue();//全局捕获
}
document.onmousemove = function(e){
e = e || window.event;
var shang1 = one.offsetTop,
xia1 = shang1 + one.offsetHeight,
zuo1 = one.offsetLeft,
you1 = zuo1 + one.offsetWidth;
//计算移动物体的边界
//左右边界到最左边的距离,上下边界到最上面的距离
if(zuo > you1 || zuo1 > you || shang > xia1 || shang1 >xia ){
two.style.background = ""
}else{
two.style.background = "yellow"
}
var left = e.clientX - w;
var topa = e.clientY - h;
//div距离窗口的位置
one.style.top = topa + "px";
one.style.left = left + "px";
// return false;//拦截浏览器默认行为
e.preventDefault();//拦截浏览器默认行为
}
document.onmouseup = function(){
document.onmouseup = null;
document.onmousemove = null;//取消事件
if(one.releaseCaptrue){
one.releaseCaptrue();
}
}
}
</script>
</body>
运动的封装
- 通过改变物体相对于父元素的left或top值实现物体的运动
- 想要改变物体的位置
- 首先明确要改变的是哪个物体的位置,所以第一个参数传入的是物体的名称
- 其次要传入第二个参数作为物体运动的方向,左右方向改变物体的left值,上下方向改变物体的top值
- 第三个参数传入物体运动的速度,为整数
- 第四个参数传入物体运动的目标值
- 根据当前位置和终点位置判断物体运动的方向
<body>
<div></div>
<div></div>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var o = document.getElementsByTagName("div");
for(var i = 0; i < o.length;i++){
o[i].onclick = function(){
run(this,'left',10,500);
}
}
//obj 运动的对象
//attr 运动对象的属性 top,left
//speed 物体运动的速度
//stopValue 终点的位置
function run(obj, attr, speed, stopValue) {
clearInterval(obj.timer);//清除自身的定时器
var l = parseInt(getSty(obj, attr));//获取物体当前的位置
speed = l < stopValue ? speed : -speed;//根据当前的位置和终点的位置,判断速度的正负
obj.timer = setInterval(function () {//定时器
l = getSty(obj, attr);//实时获取物体的位置
l = parseInt(l) + speed;//新位置
if (l >= stopValue && speed > 0 || l <= stopValue && speed < 0) {//判断是否到达终点
l = stopValue;
clearInterval(obj.timer);
}
obj.style[attr] = l + "px";
}, 50);
}
function getSty(obj, pro) {
if (obj.style[pro]) {
return obj.style[pro];
}
return getComputedStyle(obj, null)[pro];
}
</script>
</body>
多物体运动
<body>
<div style="background: red;left: 0;"></div>
<div style="background: skyblue;left: 100px;"></div>
<div style="background: lightcoral;left: 200px;"></div>
<div style="background: yellowgreen;left: 300px;"></div>
<script>
var o = document.getElementsByTagName("div");
o[0].onclick = function(){
run(this,'top',50,300);
var i = 0;
var timer = setInterval(function(){
i++;
run(o[i],'top',50,300);
if(i >= o[i].length){
clearInterval(timer);
}
},1000);
}
function run(obj, attr, speed, stopValue) {
clearInterval(obj.timer);
var l = parseInt(getSty(obj, attr));//获取当前物体的位置
speed = l < stopValue ? speed : -speed;//根据当前位置和终点位置判断运动的方向
obj.timer = setInterval(function () {
l = parseInt(getSty(obj, attr));//实时获取物体的位置
l = l + speed;//新位置
if (l >= stopValue && speed > 0 || l <= stopValue && speed < 0){
l = stopValue;
clearInterval(obj.timer);
}
obj.style[attr] = l + 'px';
}, 500);
}
function getSty(obj, pro) {
if (obj.currentStyle) {
return obj.currentStyle[pro];
}
return getComputedStyle(obj, null)[pro];
}
</script>
</body>
减速运动
<body>
<button>开始</button>
<div></div>
<script>
var o = document.querySelector('div');
document.querySelector('button').onclick = function () {
move();
};
function move() {
var timer = setInterval(function () {
if (o.offsetLeft >= 800) {
o.style.left = '800px';
clearInterval(timer);
}
var l = o.offsetLeft;
var speed = Math.floor((800 - o.offsetLeft) / 15);
o.style.left = l + speed + "px";
if(speed == 0){
o.style.left = "800px";
}
}, 50);
}
</script>
</body>
回调函数
回调函数即callback,就是你写一个函数,让预先写好的系统来调用。你调用系统的函数,是直调。让系统调用你的函数,就是回调。
<script>
//回调函数:当满足某个条件的时候由系统执行,普通函数需要主动调用才能执行
function run(fn) { //函数作为参数
setInterval(function () {
fn();
}, 1000)
}
run(function fn(){ //调用时传入一个参数
console.log(1);
});
</script>
div {
width: 100px;
height: 100px;
position: absolute;
}
</style>
</head>
<body>
<div style="background: red;left: 0;"></div>
<div style="background: skyblue;left: 100px;"></div>
<div style="background: lightcoral;left: 200px;"></div>
<div style="background: yellowgreen;left: 300px;"></div>
<script>
var ds = document.querySelectorAll('div');
var i = 0;
ds[0].onclick = function () {
move(this, 'top', 10, 300, function () {
i++;
move(ds[i], 'top', 10, 300, function () {
i++;
move(ds[i], 'top', 10, 300, function () {
i++;
move(ds[i], 'top', 10, 300);
});
});
});
}
//fn是一个函数
function move(obj, attr, speed, stopValue, fn) {
clearInterval(obj.timer);//清除之前的定时器
var l = parseInt(getStyle(obj, attr));//根据起点和终点之间的关系,判断速度是正还是负
speed = l < stopValue ? speed : -speed;
obj.timer = setInterval(function () {
l = getStyle(obj, attr);//获取当前样式属性值
l = parseInt(l) + speed;//新位置
//向左,向右
// 到达最右&&向右 ||到达最左&&向左
if (l >= stopValue && speed > 0 || l <= stopValue && speed < 0) {
l = stopValue;
}
//判断,若到达终点,停止
if (l == stopValue) {
clearInterval(obj.timer);
fn();//动画执行完毕之后,执行这个函数
}
obj.style[attr] = l + 'px';
}, 30)
}
function getStyle(obj, attr) { //找可变的量做参数 元素obj,属性:attr
if (obj.currentStyle) { //ie
return obj.currentStyle[attr];
} else { //标准
return getComputedStyle(obj)[attr];
}
}
</script>
</body>