我有一个由 9 列和 5 行组成的网格布局,因此有 45 个单元格
现在我需要在此布局中放置动态数量的圆圈。圆圈的数量从最少 1 个到最多 9 个不等。这些圆圈在网格中的位置应遵循以下规则:
所以:
圆的半径也可以变化,但目前并不重要,因为我想将圆绝对放置。
我怎样才能做到这一点?有图书馆或类似的东西可以帮助我吗? 我正在使用 React。
这里有一个codesandbox
您可以将布局存储在数组中。在下面的示例中,我创建了每个布局的压缩版本。
数字代表要跳过的单元格数量,“x”代表一个点。
const layouts = [
'', // 0
'22x22', // 1
'20x3x20', // 2
'19x2x2x19', // 3
'12x6x5x6x12', // 4
'4x14x2x2x14x4', // 5
'10x2x2x11x2x2x10', // 6
'4x5x5x5x5x5x5x4', // 7
'3x3x2x3x15x3x2x3x3', // 8
'1x2x2x11x2x2x11x2x2x1' // 9
];
const size = { rows: 5, cols: 9 };
const ctx = document.querySelector('#draw').getContext('2d');
render(ctx); // Initial render
let index = 1;
setInterval(() => {
render(ctx, layouts[index]); // Re-render every second
index = (index + 1) % layouts.length;
}, 1000);
function render(ctx, layout) {
const { width, height } = ctx.canvas;
const { rows, cols } = size;
ctx.clearRect(0, 0, width, height);
renderGrid(ctx, rows, cols, '#D1D1D1');
if (!layout) return;
const blockWidth = width / cols;
const blockHeight = height / rows;
const skips = layout.split('x').map(v => parseInt(v, 10));
const cellCount = rows * cols;
let index = 0;
while (index < cellCount) {
let skip = skips.pop();
index += skip;
if (index >= cellCount) break; // Ensure the index does not exceed the grid limit
const col = index % cols;
const row = Math.floor(index / cols);
const x = col * blockWidth;
const y = row * blockHeight;
const xOff = Math.floor(x + blockWidth / 2);
const yOff = Math.floor(y + blockHeight / 2);
const radius = Math.floor(Math.min(blockWidth, blockHeight) / 2) - 2;
renderDot(ctx, xOff, yOff, radius, '#F7A392');
index++;
}
}
function renderDot(ctx, x, y, radius, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fill();
}
function renderGrid(ctx, rows, cols, color) {
const { width, height } = ctx.canvas;
const blockWidth = width / cols;
const blockHeight = height / rows;
ctx.save();
ctx.translate(0.5, 0.5);
ctx.strokeStyle = color;
ctx.beginPath();
for (let row = 0; row < rows; row++) {
const subHeight = Math.floor(row * blockHeight);
ctx.moveTo(0, subHeight);
ctx.lineTo(width, subHeight);
}
ctx.moveTo(0, height-1);
ctx.lineTo(width, height-1);
for (let col = 0; col < cols; col++) {
const subWidth = Math.floor(col * blockWidth);
ctx.moveTo(subWidth, 0);
ctx.lineTo(subWidth, height);
}
ctx.moveTo(width-1, 0);
ctx.lineTo(width-1, height);
ctx.stroke();
ctx.restore();
}
<canvas id="draw"></canvas>