<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>canvas</title>
<style>
html,body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
}
/* 选择框样式 */
#rubberband {
width: 0;
height: 0;
border: 1px solid rgb(0 209 255);
background-color: rgba(0,209,255,0.25);
position: absolute;
z-index: 999;
}
</style>
</head>
<body>
<script>
addRubberband(document.body,{mouseup(o) {console.log(o)}})
// 添加选择框,选择框的信息会以回调函数方式返回
// @params{HTMLElement} 选择框的容器
// @params{object} mousedown,mousemove,mouseup 回调函数, 信息是第一个参数
function addRubberband(container,eventCb={}) {
let div = document.createElement("div");
let width,height,startX,startY,endX,endY,left,top;
let containerBox = {}
div.id = "rubberband";
document.body.appendChild(div)
let event = {
mousedown(e) {
containerBox = container.getBoundingClientRect(); // 实时获取最新状态
startX = left = e.clientX;
startY = top = e.clientY;
window.addEventListener("mousemove",event.mousemove)
eventCb.mousedown && eventCb.mousedown(div.getDivRect())
},
mousemove(e) {
endX = e.clientX;
endY = e.clientY;
width = endX - startX;
height = endY - startY;
// x反向选择
if (startX > endX) {
width = Math.abs(startX - endX);
left = startX-Math.abs(startX - endX);
}
// y反向选择
if (startY > endY) {
height = Math.abs(startY - endY);
top = startY-Math.abs(startY - endY);
}
// 选框不超出容器才渲染
if (
left >= containerBox.left &&
endX <= (containerBox.left+containerBox.width) &&
top >= containerBox.top &&
endY <= (containerBox.top+containerBox.height)
) {
event.updateStyle();
}
eventCb.mousemove && eventCb.mousemove(div.getDivRect())
},
mouseup(e) {
window.removeEventListener("mousemove",event.mousemove);
eventCb.mouseup && eventCb.mouseup(event.getDivRect())
div.style.display = "none"
width = height = 0;
},
// 更新选择框样式
updateStyle() {
div.style = `
display: block;
left: ${left}px;
top: ${top}px;
width: ${width}px;
height: ${height}px
`;
},
// 获取选择框信息,选择框定位信息是相对于容器的
getDivRect() {
let {left,top,width,height} = div.getBoundingClientRect();
return {
startX: left-containerBox.left,
startY: top - containerBox.top,
endX: left-containerBox.left+width,
endY: top-containerBox.top+height,
width,height
}
}
}
container.addEventListener("mousedown",event.mousedown)
window.addEventListener("mouseup",event.mouseup)
}
</script>
</body>
</html>
注意:
- 默认会向window 添加了 mouseup 事件
- 选择框信息有 宽高,定位
- 移动端需要将鼠标事件换成touch事件,把 e.clientX 替换成 e.targetTouches[0].clientX, e.clientY 也同理