合并宫格,并且判断所选的是否为矩形
背景
需要做一个多宫格合并的功能,并且判断是否为矩形,不是矩形不能合并,并且提示。
实现逻辑步骤
1.动态生成 N 宫格;
2.点击单元格选中;
3.判断选中宫格合并是否为常规矩形;
4.合并;
注意
因为是基于vue写的(比较方便),要到官网或者github下载相应的依赖 vue.min.js,才可以正常启动代码。如果有可用的CDN也可替换
效果


代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>合并单元格</title>
<script src="./vue.min.js"></script>
<style>
.grid-box {
width: 500px;
height: 500px;
display: grid;
grid-auto-flow: column dense;
}
.grid-box-item {
border: 2px solid black;
cursor: pointer;
}
.choosed {
border-color: red;
}
</style>
</head>
<body>
<div id="app">
<div class="grid-box" id="box">
<div class="grid-box-item" v-for="(item, index) in gridList" :key="index" ref=""
@click="handleCellClick(item)" :style="{ ...item.style }" :class="{ choosed: item.choosed }"></div>
</div>
<button @click="merge">merge</button>
</div>
</body>
<script>
new Vue({
el: '#app',
data() {
return {
gridList: [],
choosedList: [],
row: 3,
column: 3,
};
},
mounted() {
this.createTable();
},
methods: {
debounce(fn, wait) {
if (timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
},
createTable() {
this.gridList = [];
let id = 1;
for (let i = 1; i <= this.row; i++) {
for (let j = 1; j <= this.column; j++) {
let item = {
id,
choosed: false,
gridColumnStart: j,
gridColumnEnd: j + 1,
gridRowStart: i,
gridRowEnd: i + 1,
cellNum: 1,
};
item.style = {};
item.style.gridArea = item.style.gridColumn =
item.gridRowStart +
" / " +
item.gridColumnStart +
" / " +
item.gridRowEnd +
" / " +
item.gridColumnEnd;
this.gridList.push(item);
id = id + 1;
}
}
let box = document.getElementById("box");
box.style.gridTemplateColumns = this.column;
box.style.gridTemplateRows = this.row;
},
merge() {
let colStart, colEnd, rowStart, rowEnd;
let selectedCellCout = 0;
let result;
for (let item of this.choosedList) {
selectedCellCout = selectedCellCout + item.cellNum;
if (item.gridColumnStart < colStart || !colStart) {
colStart = item.gridColumnStart;
}
if (item.gridRowStart < rowStart || !rowStart) {
rowStart = item.gridRowStart;
}
if (item.gridColumnEnd > colEnd || !colEnd) {
colEnd = item.gridColumnEnd;
}
if (item.gridRowEnd > rowEnd || !rowEnd) {
rowEnd = item.gridRowEnd;
}
}
console.log(this.choosedList);
console.log(selectedCellCout);
console.log((rowEnd - rowStart) * (colEnd - colStart));
if (selectedCellCout != (rowEnd - rowStart) * (colEnd - colStart)) {
console.log("not a square");
return false;
}
result = this.choosedList.shift();
result.style.gridArea =
rowStart + " / " + colStart + " / " + rowEnd + " / " + colEnd;
result.gridColumnStart = colStart;
result.gridColumnEnd = colEnd;
result.gridRowStart = rowStart;
result.gridRowEnd = rowEnd;
result.cellNum = result.cellNum + this.choosedList.length;
this.gridList = this.gridList.filter((item) => {
let index = this.choosedList.findIndex((el) => {
return el.id == item.id;
});
return index == -1;
});
this.choosedList = [result];
},
handleCellClick(item) {
if (!item.choosed) {
item.choosed = true;
this.choosedList.push(item);
} else {
let index = this.choosedList.findIndex((el) => {
return el.id == item.id;
});
if (index > -1) {
item.choosed = false;
this.choosedList.splice(index, 1);
}
}
},
},
})
</script>
</html>