<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device - width, initial - scale = 1.0">
<style>
table {
border-collapse: collapse;
cursor: pointer;
}
table td {
border: 1px solid black;
padding: 5px;
}
.selected {
background-color: lightblue;
}
.selected-group {
border-top: 2px solid green !important;
border-bottom: 2px solid green !important;
border-left: 2px solid green !important;
border-right: 2px solid green !important;
}
.selected-group1 {
border-top: 2px solid green !important;
}
.selected-group2 {
border-bottom: 2px solid green !important;
}
.selected-group3 {
border-left: 2px solid green !important;
}
.selected-group4 {
border-right: 2px solid green !important;
}
::selection {
background-color: transparent;
}
</style>
</head>
<body>
<span onclick="redata()">1111</span>
<button onclick="createTable()">创建表格</button>
<div id="table-container"></div>
<script>
// 开始单元格
let startCell;
// 是否在拖拽中
let isDragging = false;
// 选中的单元格
let selectedCells = [];
function createTable () {
const table = document.createElement('table');
table.id = 'myTable';
for (let i = 0; i < 5; i++) {
const row = document.createElement('tr');
for (let j = 0; j < 5; j++) {
const cell = document.createElement('td');
cell.textContent = `Cell ${i * 5 + j + 1}`;
// 为每个单元格添加监听事件
cell.addEventListener('mousedown', function (e) {
startCell = this;
isDragging = true;
selectCell(this);
});
// 鼠标划过事件
cell.addEventListener('mouseover', function () {
if (isDragging) {
console.log('4');
selectCell(this);
}
});
// 鼠标抬起时清空
cell.addEventListener('mouseup', function () {
isDragging = false;
});
// 鼠标点击时事件
cell.addEventListener('click', function () {
if (!isDragging) {
toggleCellSelection(this);
}
});
row.appendChild(cell);
}
table.appendChild(row);
}
const tableContainer = document.getElementById('table-container');
tableContainer.innerHTML = '';
tableContainer.appendChild(table);
}
// 鼠标放下
function selectCell (cell) {
// 清空之前的选项
clearSelection();
// 初始点击的单元格的行与列
const startRowIndex = startCell.parentNode.rowIndex;
const startCellIndex = Array.from(startCell.parentNode.cells).indexOf(startCell);
// console.log('行:',startRowIndex,'列:',startCellIndex);
// 当前划过的行与列
const endRowIndex = cell.parentNode.rowIndex;
const endCellIndex = Array.from(cell.parentNode.cells).indexOf(cell);
// console.log('行:',endRowIndex,'列:',endCellIndex);
// 正着选倒着选都行
for (let row = Math.min(startRowIndex, endRowIndex); row <= Math.max(startRowIndex, endRowIndex); row++) {
// 获取table表格中相应行数据内全部单元格数组
const rowCells = document.getElementById('myTable').rows[row].cells;
for (let col = Math.min(startCellIndex, endCellIndex); col <= Math.max(startCellIndex, endCellIndex); col++) {
rowCells[col].classList.add('selected');
selectedCells.push(rowCells[col]);
}
}
updateGroupBorder();
}
function toggleCellSelection (cell) {
if (cell.classList.contains('selected')) {
cell.classList.remove('selected');
selectedCells = selectedCells.filter(c => c !== cell);
} else {
cell.classList.add('selected');
selectedCells.push(cell);
}
updateGroupBorder();
}
// 鼠标放下首现清空选择
function clearSelection () {
const allSelected = document.getElementsByClassName('selected');
console.log(allSelected.length, 'allSelected.length');
while (allSelected.length > 0) {
allSelected[0].classList.remove('selected');
}
selectedCells = [];
removeGroupBorder();
}
function updateGroupBorder () {
removeGroupBorder();
if (selectedCells.length > 0) {
const minRowIndex = Math.min.apply(null, Array.from(selectedCells).map(cell => cell.parentNode.rowIndex));
const maxRowIndex = Math.max.apply(null, Array.from(selectedCells).map(cell => cell.parentNode.rowIndex));
const minCellIndex = Math.min.apply(null, Array.from(selectedCells).map(cell => Array.from(cell.parentNode.cells).indexOf(cell)));
const maxCellIndex = Math.max.apply(null, Array.from(selectedCells).map(cell => Array.from(cell.parentNode.cells).indexOf(cell)));
const table = document.getElementById('myTable');
// 顶部边框
for (let col = minCellIndex; col <= maxCellIndex; col++) {
table.rows[minRowIndex].cells[col].classList.add('selected-group1');
}
// 底部边框
for (let col = minCellIndex; col <= maxCellIndex; col++) {
table.rows[maxRowIndex].cells[col].classList.add('selected-group2');
}
// 左边框
for (let row = minRowIndex; row <= maxRowIndex; row++) {
table.rows[row].cells[minCellIndex].classList.add('selected-group3');
}
// 右边框
for (let row = minRowIndex; row <= maxRowIndex; row++) {
table.rows[row].cells[maxCellIndex].classList.add('selected-group4');
}
}
}
// 清除外边框
function removeGroupBorder () {
const allGroupBordered1 = document.getElementsByClassName('selected-group1');
while (allGroupBordered1.length > 0) {
allGroupBordered1[0].classList.remove('selected-group1');
}
const allGroupBordered2 = document.getElementsByClassName('selected-group2');
while (allGroupBordered2.length > 0) {
allGroupBordered2[0].classList.remove('selected-group2');
}
const allGroupBordered3 = document.getElementsByClassName('selected-group3');
while (allGroupBordered3.length > 0) {
allGroupBordered3[0].classList.remove('selected-group3');
}
const allGroupBordered4 = document.getElementsByClassName('selected-group4');
while (allGroupBordered4.length > 0) {
allGroupBordered4[0].classList.remove('selected-group4');
}
}
function redata () {
let sumNumbers = 0;
let i = 1;
while (i <= 10) {
sumNumbers += i;
i++;
console.log(i);
}
}
</script>
</body>
</html>
主要是通过事件的监听来实现选中初始的行和列的定位,和终点的行和列的定位,然后根据四个点找到所在区域内的所有cell,找到之后判断位置,分别加上上,下,左,右四种边框。这是主要实现的思路,
然后还涉及到的就是清空操作,一般就是每移动一次都要进行大量的操作,所以只是能实现了。