【前端】如何实现框选多个元素,并且可以进行放大缩小等操作?
想实现一个类似于下面这个图片的效果,这只是个简单的,后续可能还要加上放大缩小等操作。
大家有什么好的组件或者思路嘛?
回答
这个也就是制造一个模拟框,覆盖上去,然后改变背景颜色,也就是鼠标拖拽事件,这里是你想要的效果。
框选同时按住 SHIFT 为增加选择
框选同时按住 ALT 为从已有选择种删除
<!DOCTYPE html><html>
<head>
<meta charset="UTF-8">
<title>Batch Select</title>
<style type="text/css">
.flex-row {display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;}
.flex-row > .flex-main {-webkit-flex:1 1 auto;flex:1 1 auto;}
.flex-row > .flex-side {-webkit-flex:0 0 auto;flex:0 0 auto;}
.flex-column {display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;}
.flex-column > .flex-main {-webkit-flex:1 1 auto;flex:1 1 auto;}
.flex-column > .flex-side {-webkit-flex:0 0 auto;flex:0 0 auto;}
.template {display:none;}
.cell-matrix {position:relative;padding:0.5em;background-color:#EEE;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;}
.cell-matrix .select {position:absolute;display:none;border:1px dashed rgba(0,0,255,0.7);background-color:rgba(0,0,255,0.3);box-sizing:border-box;}
.cell-matrix .cell-list {margin:0.5em 0;}
.cell-matrix .cell-list .cell-group {white-space:nowrap;}
.cell-matrix .cell-list .cell-group .cell {display:inline-block;background-color:#FFF;box-shadow:0 0 0 1px #CCC;}
.cell-matrix .cell-list .cell-group .cell-select {background-color:#00F;}
.cell-matrix .cell-list .cell-group .gap {display:inline-block;}
.cell-data {white-space:pre;}
</style>
<script>
document.addEventListener('DOMContentLoaded', function(){
let domTpl = document.querySelector('.template .cell-group');
let arrDomCellList = document.querySelectorAll('.cell-list');
let i, domCellList, dom;
for(i=0; i<arrDomCellList.length; i++)
{
domCellList = arrDomCellList[i];
for(let j=0; j<4; j++)
{
dom = domTpl.cloneNode(true);
domCellList.appendChild(dom);
}
}
let domMatrix = document.querySelector('.cell-matrix');
let MODE_SET = 1;
let MODE_ADD = 2;
let MODE_DEL = 3;
let SelectArea = {
domBase : domMatrix,
dom : domMatrix.querySelector('.select'),
on : false,
mode : MODE_SET,
x1 : 0,
y1 : 0,
x2 : 0,
y2 : 0,
};
function update_select_cell()
{
let x1 = Math.min(SelectArea.x1, SelectArea.x2) + SelectArea.domBase.offsetLeft - SelectArea.domBase.scrollLeft;
let y1 = Math.min(SelectArea.y1, SelectArea.y2) + SelectArea.domBase.offsetTop - SelectArea.domBase.scrollTop;
let x2 = Math.max(SelectArea.x1, SelectArea.x2) + SelectArea.domBase.offsetLeft - SelectArea.domBase.scrollLeft;
let y2 = Math.max(SelectArea.y1, SelectArea.y2) + SelectArea.domBase.offsetTop - SelectArea.domBase.scrollTop;
let arrData = [];
let arrDomCellList = document.querySelectorAll('.cell-list');
let i, domCellList;
for(i=0; i<arrDomCellList.length; i++)
{
domCellList = arrDomCellList[i];
let data = '';
let arrDomCell = domCellList.querySelectorAll('.cell');
let j, domCell, rect, flag;
for(j=0; j<arrDomCell.length; j++)
{
domCell = arrDomCell[j];
rect = domCell.getBoundingClientRect();
flag = ! (x2 < rect.left
|| y2 < rect.top
|| x1 > rect.right
|| y1 > rect.bottom);
switch(SelectArea.mode)
{
case MODE_ADD:
if(flag === true)
{
data += '1';
domCell.classList.add('cell-select');
}
else
{
data += (domCell.classList.contains('cell-select')?'1':'0');
}
break;
case MODE_DEL:
if(flag === true)
{
data += '0';
domCell.classList.remove('cell-select');
}
else
{
data += (domCell.classList.contains('cell-select')?'1':'0');
}
break;
default:
if(flag === true)
{
data += '1';
domCell.classList.add('cell-select');
}
else
{
data += '0';
domCell.classList.remove('cell-select');
}
break;
}
}
arrData.push(data);
}
return arrData;
}
function update_select_rect()
{
if(SelectArea.on === false)
{
SelectArea.dom.style.display = 'none';
let arrData = update_select_cell();
document.querySelector('.cell-data').innerHTML = arrData.join('\n');
SelectArea.x1 = 0;
SelectArea.y1 = 0;
SelectArea.x2 = 0;
SelectArea.y2 = 0;
return;
}
SelectArea.dom.style.display = 'block';
SelectArea.dom.style.top = Math.min(SelectArea.y1, SelectArea.y2) + 'px';
SelectArea.dom.style.left = Math.min(SelectArea.x1, SelectArea.x2) + 'px';
SelectArea.dom.style.width = Math.abs(SelectArea.x1 - SelectArea.x2) + 'px';
SelectArea.dom.style.height = Math.abs(SelectArea.y1 - SelectArea.y2) + 'px';
}
domMatrix.addEventListener('mousedown', function($evt){
if(($evt.buttons & 0x01) !== 0x01)
return;
SelectArea.on = true;
SelectArea.x1 = $evt.clientX - SelectArea.domBase.offsetLeft + SelectArea.domBase.scrollLeft;
SelectArea.y1 = $evt.clientY - SelectArea.domBase.offsetTop + SelectArea.domBase.scrollTop;
SelectArea.x2 = SelectArea.x1;
SelectArea.y2 = SelectArea.y1;
update_select_rect();
});
domMatrix.addEventListener('mouseup', function($evt){
if(SelectArea.on === false)
return;
if(($evt.buttons & 0x01) !== 0x00)
return;
if($evt.shiftKey === true)
SelectArea.mode = MODE_ADD;
else if($evt.altKey === true)
SelectArea.mode = MODE_DEL;
else
SelectArea.mode = MODE_SET;
SelectArea.on = false;
SelectArea.x2 = $evt.clientX - SelectArea.domBase.offsetLeft + SelectArea.domBase.scrollLeft;
SelectArea.y2 = $evt.clientY - SelectArea.domBase.offsetTop + SelectArea.domBase.scrollTop;
update_select_rect();
});
domMatrix.addEventListener('mousemove', function($evt){
if(SelectArea.on === false)
return;
if(($evt.buttons & 0x01) !== 0x01)
return;
SelectArea.x2 = $evt.clientX - SelectArea.domBase.offsetLeft + SelectArea.domBase.scrollLeft;
SelectArea.y2 = $evt.clientY - SelectArea.domBase.offsetTop + SelectArea.domBase.scrollTop;
update_select_rect();
});
});
</script>
</head>
<body>
<div class="cell-matrix">
<div class="select"></div>
<div class="flex-row cell-list">
<div class="flex-side">星期一</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期二</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期三</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期四</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期五</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期六</div>
<div class="gap"> </div>
</div>
<div class="flex-row cell-list">
<div class="flex-side">星期日</div>
<div class="gap"> </div>
</div>
</div>
<div class="cell-data"></div>
<div class="template">
<div class="flex-side cell-group">
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="gap"> </div>
</div>
</div>
</body>
</html>
以上是 【前端】如何实现框选多个元素,并且可以进行放大缩小等操作? 的全部内容, 来源链接: utcz.com/a/80129.html