需求:大的容器内有18个3行6列的正方形格子,用户添加图片可以选择1x1、1x2、2x1、2x2的格式上传图片会填充到大容器内,1x1是占一个格子,1x2是一行横着占2个格子,2x1是竖着占两个格子,2x2是横竖占2格共4个格子;用户会选不同格式上传图片填充满整个3x6的容器。
如下是3x6的盒子
用户选择添加1x1的图如下会填充
用户随机选择不同格式的添加直到填满盒子
实现思路:定义一个二维数组,也是3x6的点阵,初始值是0,添加不同格式把数组改成1即为填充,再定义一个数组存储用户选择的不同格式点阵,并记录在3x6数组中的位置
实例代码实现:
html部分
<template>
<div>
<button @click="addBox('1x1')">添加1x1</button>
<button @click="addBox('2x1')">添加2x1</button>
<button @click="addBox('1x2')">添加1x2</button>
<button @click="addBox('2x2')">添加2x2</button>
<div class="grid-box">
<div
v-for="(item, index) in replenish()"
:key="index"
:class="['grid-item', {'def-box': item.layout.default}]"
:style="{
'grid-area': `${item.layout.star} / ${item.layout.end} / span ${item.layout.row} / span ${item.layout.column}`
}"
></div>
</div>
</div>
</template>
以上代码是添加不同格式的按钮和3x6的容器,使用网格布局grid-item属性
grid-area:开始行的位置 / 开始列的位置 / span 行所占的格子数量 / span 列所占的格子数量
<script>
export default {
data () {
return {
matrix: [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
], // 定义3行6列的二维数组
emptyCells: [] // 定义空盒子的数组
}
},
methods: {
// 添加盒子的函数
addBox (size) {
const matrix = this.matrix
let flag = false
let layout = {}
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (size === '1x1') {
if (matrix[i][j] === 0) {
matrix[i][j] = 1
flag = true
layout = { star: i + 1, end: j + 1, row: 1, column: 1 }
break
}
} else if (size === '1x2') {
if (matrix[i][j] === 0 && matrix[i][j + 1] === 0) {
matrix[i][j] = 1
matrix[i][j + 1] = 1
flag = true
layout = { star: i + 1, end: j + 1, row: 1, column: 2 }
break
}
} else if (size === '2x1') {
if (matrix[i][j] === 0 && matrix[i + 1] && matrix[i + 1][j] === 0) {
matrix[i][j] = 1
matrix[i + 1][j] = 1
flag = true
layout = { star: i + 1, end: j + 1, row: 2, column: 1 }
break
}
} else if (size === '2x2') {
if (matrix[i][j] === 0 &&
matrix[i][j + 1] === 0 &&
matrix[i + 1] &&
matrix[i + 1][j] === 0 &&
matrix[i + 1][j + 1] === 0
) {
matrix[i][j] = 1
matrix[i][j + 1] = 1
matrix[i + 1][j] = 1
matrix[i + 1][j + 1] = 1
flag = true
layout = { star: i + 1, end: j + 1, row: 2, column: 2 }
break
}
}
}
if (flag) break
}
// 没有合适的空位放了
if (!flag) {
console.log('没有合适的位置了')
return
}
// 将盒子的大小和位置添加到空盒子的数组中
this.emptyCells.push({ size: size, layout })
console.log('this.emptyCells:', this.emptyCells)
console.log('this.matrix:', this.matrix)
this.replenish()
},
// 补充剩余的盒子
replenish () {
const matrix = this.matrix
const box = JSON.parse(JSON.stringify(this.emptyCells))
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] === 0) {
const layout = { star: i + 1, end: j + 1, row: 1, column: 1, default: true }
box.push({ size: '1x1', layout })
}
}
}
return box
}
}
}
</script>
1.addBox是处理添加不同格式的盒子并且记录盒子所在的位置和行列占几个格子刚好是网格布局grid-item所需要的,
2.replenish是补充空的盒子确保这个网格一直是18个,因为网格布局的原因需要所有格子都有才会,不然会出现布局样式问题
<style scoped>
.grid-box {
display: grid;
grid-template-columns: auto auto auto auto auto auto;
grid-gap: 20px;
background-color: #2196F3;
padding: 10px;
box-sizing: border-box;
width: 700px;
height: 340px;
}
.grid-item {
background: #ccc;
}
.def-box {
background: #FFFFFF;
}
</style>
grid-box容器设置成网格布局,grid-template-columns定义一行6个格子,grid-gap定义格子上下左右间隔20px,宽是700px一行是6个盒子加上5个间隙20就是100,那么每个盒子宽度就是100px,高度是340px,18个盒子,一行显示6个,那就是3行,2个间隙20就是40,那么每个盒子的高度就是100px,得到3行6列的盒子都是宽*高就是100*100像素的
以上代码可以复制到vue文件中注册一个路由访问体验,有任何不对的地方和可以优化的点欢迎留言指教谢谢