代码拉取完成,页面将自动刷新
OOP (Object Oriented Programming): 面向(Oriented)对象(Object)的程序设计(Programming)
类: 抽取想象的功能,把他们归在一类
什么是面向对象编程
对程序的功能进行抽象,把相似的功能封装成一个类,在使用时,使用的是类的实例化对象。
addEventListener(event, function, useCapture)
removeEventListener
getComputedStyle(element, pseudoElement)
方法用于获取指定元素的 CSS 样式(pseudoElement
:伪元素)
elment.getBoundingClientRect()
用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置
获取的样式是元素在浏览器中最终渲染效果的样式
事件池:存储相应的事件
事件添加机制:添加相应的事件处理函数 实例.on('事件名称', e => {})
事件删除机制:删除相应的事件处理函数 实例.off('事件名称', e => {})
事件触发机制:如何触发对应的事件 实例.dispatch('事件名称', e)
class Event {
constructor() {
/*
* this.events = {
click: [f1,f2,f3],
mousemove: [f1,f2,f3]
}
*/
this.events = {}; // 事件池
}
// 添加相应的事件处理
on(evnet, fn) {
if (!this.events[evnet]) {
this.events[evnet] = [];
}
this.events[evnet].push(fn);
}
// 删除相应的事件处理
off(evnet, fn) {
if (this.events[evnet]) {
this.events[evnet] = this.events[evnet].filter(
(item) => fn != item
);
}
}
// 触发相应的事件处理
dispatch(event, ...arg) {
if (this.events[event]) {
this.events[event].forEach((item) => {
item.call(this, ...arg); // 从window => 指向实例化对象
});
}
}
}
class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
// class Child {
// constructor(name, age) {
// this.name = name;
// this.age = age;
// }
// sayName() {
// console.log(this.name);
// }
// sayAge() {
// console.log(this.age);
// }
// }
// 继承:把父类的属性和方法都拿过来
class Child extends Parent {
constructor(name, age) {
super(name); // 继承父类的构造函数
this.age = age;
}
sayAge() {
console.log(this.age);
}
}
let child = new Child("KKB", 18)
child.sayName()
child.sayAge()
提取拖拽跟框选共同的功能留在Drag类,差异部分功能交给实例的自定义事件处理
class Drag extends Event {
constructor(el) {
super();
this.el = el;
this.startMouse = {}; // 按下时,鼠标坐标
let move = (e) => {
this.move(e);
};
this.el.addEventListener("mousedown", (e) => {
this.start(e);
document.addEventListener("mousemove", move);
document.addEventListener(
"mouseup",
() => {
this.end(e);
document.removeEventListener("mousemove", move);
},
{ once: true }
);
});
}
start(e) {
/*
* 拖拽:获取按下时元素坐标
* 框选:创建元素用于画框
*/
this.startMouse = {
x: e.clientX,
y: e.clientY,
};
this.dispatch("dragstart", e);
}
move(e) {
/*
* 拖拽:用按下时元素坐标+差值,计算当前元素的坐标
* 框选:计算框的宽、高、left、top
*/
let nowMouse = {
x: e.clientX,
y: e.clientY,
};
let dis = {
x: nowMouse.x - this.startMouse.x,
y: nowMouse.y - this.startMouse.y,
};
this.dispatch("dragmove", e, dis, nowMouse);
}
end(e) {
/*
* 拖拽:不作处理
* 框选:移除框
*/
this.dispatch("dragend", e);
}
}
拖拽
let box = document.querySelector("#box");
let boxDrag = new Drag(box);
let startOffset = {}; // 按下时,元素坐标
boxDrag.on("dragstart", (e) => {
console.log("开始拖拽时执行", e);
startOffset = {
x: parseFloat(getComputedStyle(box)["left"]),
y: parseFloat(getComputedStyle(box)["top"]),
};
e.stopPropagation();
});
boxDrag.on("dragmove", (e, dis, now) => {
console.log("拖拽中执行", e, dis, now);
let nowOffset = {
x: dis.x + startOffset.x,
y: dis.y + startOffset.y,
};
box.style.left = nowOffset.x + "px";
box.style.top = nowOffset.y + "px";
});
框选
let selectDrag = new Drag(document);
let select = null; // 记录元素
selectDrag.on("dragstart", (e) => {
start = {
x: e.clientX,
y: e.clientY,
};
select = document.createElement("div");
select.className = "selectBox";
document.body.appendChild(select);
e.stopPropagation();
});
selectDrag.on("dragmove", (e, dis, now) => {
// 框的宽度:两个坐标点的横向差值
select.style.width = Math.abs(dis.x) + "px";
// 框的高度:两个坐标点的纵向差值
select.style.height = Math.abs(dis.y) + "px";
// 框的left:两个坐标点靠近左侧的横坐标(较小的值)
select.style.left = Math.min(now.x, selectDrag.startMouse.x) + "px";
// 框的top:两个坐标点靠近上方的纵坐标(较小的值)
select.style.top = Math.min(now.y, selectDrag.startMouse.y) + "px";
});
selectDrag.on("dragend", (e) => {
select.remove();
});
注意
在拖拽元素上的mousedown事件会冒泡给到document,从而触发框选的功能
因而需要通过e.stopPropagation();
进行阻止冒泡
class DragEl extends Drag {
constructor(...arg) {
super(...arg);
this.startOffset = {};
this.on("dragstart", (e) => {
this.dragStart(e);
});
this.on("dragmove", (e, dis, now) => {
this.dragMove(e, dis, now);
});
}
dragStart(e) {
this.startOffset = {
x: parseFloat(getComputedStyle(this.el)["left"]),
y: parseFloat(getComputedStyle(this.el)["top"]),
};
}
dragMove(e, dis, now) {
let nowOffset = {
x: this.startOffset.x + dis.x,
y: this.startOffset.y + dis.y,
};
this.el.style.left = nowOffset.x + "px";
this.el.style.top = nowOffset.y + "px";
}
}
let boxDrag = new DragEl(document.querySelector("#box"));
boxDrag.on("dragstart", (e) => {
e.stopPropagation(); // 处理冒泡
});
class DragSelect extends Drag {
constructor(...arg) {
super(...arg);
this.select = null;
this.startOffset = {};
this.on("dragstart", (e) => {
this.dragStart(e);
});
this.on("dragmove", (e, dis, now) => {
this.dragMove(e, dis, now);
});
this.on("dragend", (e) => {
this.dragEnd(e);
});
}
dragStart(e) {
this.startOffset = {
x: e.clientX,
y: e.clientY,
};
this.select = document.createElement("div");
this.select.className = "selectBox";
document.body.appendChild(this.select);
e.stopPropagation(); // 处理冒泡
}
dragMove(e, dis, now) {
// 框的宽度:两个坐标点的横向差值
this.select.style.width = Math.abs(dis.x) + "px";
// 框的高度:两个坐标点的纵向差值
this.select.style.height = Math.abs(dis.y) + "px";
// 框的left:两个坐标点靠近左侧的横坐标(较小的值)
this.select.style.left = Math.min(now.x, this.startMouse.x) + "px";
// 框的top:两个坐标点靠近上方的纵坐标(较小的值)
this.select.style.top = Math.min(now.y, this.startMouse.y) + "px";
}
dragEnd(e) {
this.select.remove();
}
}
let selectDrag = new DragSelect(document);
碰撞检测:哪些条件发生碰撞 => 哪些条件不发生碰撞
<style>
#box {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background: red;
}
#box2 {
position: absolute;
left: calc(50% - 100px);
top: calc(50% - 100px);
width: 100px;
height: 100px;
background: yellow;
z-index: 2;
}
.box3 {
float: left;
margin-right: 50px;
width: 100px;
height: 100px;
background: blue;
z-index: 2;
}
</style>
<div id="box"></div>
<div id="box2"></div>
<div class="box3"></div>
<div class="box3"></div>
<div class="box3"></div>
<div class="box3"></div>
<div class="box3"></div>
<script>
function boom(el1, el2) {
let el1Rect = el1.getBoundingClientRect();
let el2Rect = el2.getBoundingClientRect();
if (
el1Rect.right < el2Rect.left ||
el1Rect.left > el2Rect.right ||
el1Rect.bottom < el2Rect.top ||
el1Rect.top > el2Rect.bottom
) {
return false;
}
return true;
}
{
let box = document.querySelector("#box");
let box2 = document.querySelector("#box2");
let box3 = document.querySelectorAll(".box3");
let boxDrag = new DragEl(box);
boxDrag.on("dragmove", () => {
if (boom(box, box2)) {
box.style.background = "green";
} else {
box.style.background = "red";
}
box3.forEach((item) => {
if (boom(box, item)) {
// box.style.background = "green"; // 经过循环后,依旧是未碰撞的情况
item.style.background = "green";
} else {
item.style.background = "blue";
}
});
});
}
</script>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。