效果图
先看实现效果:
UI
先写出html代码:
css代码:
这样就得到了基础UI样式:
实现逻辑
主要思路:
1、通过鼠标监听事件实现遮罩层效果
将遮罩层盒子设置为Fixed布局,动态设置盒子的坐标和大小
clientX, clientY可获取当前鼠标相对于屏幕的坐标,可将其赋予盒子坐标
盒子大小可以用鼠标起始坐标 startX,startY减去clientX, clientY
注意点:
鼠标往右上、右下、左上、左下要有不同的考虑。可以通过比较clientX,clientY和startX,startY来判断方位
2、鼠标移动监听事件的逻辑
若直接添加鼠标移动监听事件则会大大影响性能
正常逻辑是:当鼠标点击时添加监听事件,鼠标升起时移除监听事件。
重点是:监听事件和取消监听的回调函数使用匿名函数是没用的
若直接删除监听事件比如:
window.addEventListener("scroll", (event)=>{
this.handeScroll(event)
}, true),
window.removeEventListener("scroll", (event)=>{
this.handeScroll(event)
}, true),
当前的代码相当于新建了一个函数,然后试图从 window 的监听列表里移除。这样的删除方法是没用的。addEventListener 的函数和 removeEventListener 的函数一定要是一个函数。可以用全局变量、也可以自己保存。解决方法也很简单:用一个函数包裹这个请求的函数就可以了,如下面的解决方法
const handMove = (event) => {
this.move(event)
}
window.addEventListener('mousemove', handMove, true)
window.removeEventListener('mousemove', handMove, true)
这样就可以正常删除监听事件
3、方块变色逻辑
通过vue的ref属性和$refs获取dom元素
然后可以用getBoundingClientRect()方法获取当前dom元素的位置
方块变色也是要分左上、左下、右上、右下来考虑的
完整逻辑代码
export default {
name: 'App',
data() {
return {
rangeNumber: 10,
style: {
position: 'fixed',
width: '0px',
height: '0px',
top: 0,
left: 0,
},
startX: 0,
startY: 0
}
},
mounted() {
const handMove = (event) => {
this.move(event)
}
window.addEventListener('mousedown', (event) => {
let { clientX, clientY } = event
this.style.top = clientY + 'px'
this.style.left = clientX + 'px'
this.startX = clientX
this.startY = clientY
window.addEventListener('mousemove', handMove, true)
})
window.addEventListener('mouseup', () => {
this.style.width = '0px'
this.style.height = '0px'
this.$refs.box.forEach(e => {
e.style.backgroundColor = 'greenyellow'
})
window.removeEventListener('mousemove', handMove, true)
})
},
methods: {
move(event) {
let { clientX, clientY } = event;
//遮罩层逻辑
if (clientX < this.startX) {
this.style.left = clientX + 'px'
this.style.width = this.startX - clientX + 'px'
} else {
this.style.width = clientX - this.startX + 'px'
}
if (clientY < this.startY) {
this.style.top = clientY + 'px'
this.style.height = this.startY - clientY + 'px'
} else {
this.style.height = clientY - this.startY + 'px'
}
//方块变色逻辑
// 鼠标往右下角移动
if (clientY > this.startY && clientX > this.startX) {
this.$refs.box.forEach(e => {
let target = e.getBoundingClientRect()
if (target.x + 60 < clientX && target.y + 60 < clientY) {
e.style.backgroundColor = 'green'
} else {
e.style.backgroundColor = 'greenyellow'
}
// 起始点在点击坐标之后的不改变颜色
if (target.x < this.startX || target.y < this.startY) {
e.style.backgroundColor = 'greenyellow'
}
})
}
// 鼠标往左下角移动
else if (clientY > this.startY && clientX < this.startX) {
this.$refs.box.forEach(e => {
let target = e.getBoundingClientRect()
if (target.x > clientX && target.y + 60 < clientY) {
e.style.backgroundColor = 'green'
} else {
e.style.backgroundColor = 'greenyellow'
}
// 起始点在点击坐标之后的不改变颜色
if (target.x + 60 > this.startX || target.y < this.startY) {
e.style.backgroundColor = 'greenyellow'
}
})
}
// 鼠标往右上角移动
else if (clientY < this.startY && clientX > this.startX) {
this.$refs.box.forEach(e => {
let target = e.getBoundingClientRect()
if (target.x + 60 < clientX && target.y > clientY) {
e.style.backgroundColor = 'green'
} else {
e.style.backgroundColor = 'greenyellow'
}
// 起始点在点击坐标之后的不改变颜色
if (target.x < this.startX || target.y + 60 > this.startY) {
e.style.backgroundColor = 'greenyellow'
}
})
}
// 鼠标往左上角移动
else if (clientY < this.startY && clientX < this.startX) {
this.$refs.box.forEach(e => {
let target = e.getBoundingClientRect()
if (target.x > clientX && target.y > clientY) {
e.style.backgroundColor = 'green'
} else {
e.style.backgroundColor = 'greenyellow'
}
// 起始点在点击坐标之后的不改变颜色
if (target.x + 60 > this.startX || target.y + 60 > this.startY) {
e.style.backgroundColor = 'greenyellow'
}
})
}
},
}
}