如何将元素放置在网格中[关闭]

问题描述 投票:0回答:1

我有一个由 9 列和 5 行组成的网格布局,因此有 45 个单元格 enter image description here

现在我需要在此布局中放置动态数量的圆圈。圆圈的数量从最少 1 个到最多 9 个不等。这些圆圈在网格中的位置应遵循以下规则:

enter image description here

所以:

  • 如果圆的数量为1,则圆心应在第5列第3行的单元格中
  • 如果圆圈数为2,则第一个圆心应位于第3列第3行的单元格中,第二个圆心应位于第7列第3行的单元格中
  • ...

圆的半径也可以变化,但目前并不重要,因为我想将圆绝对放置。

我怎样才能做到这一点?有图书馆或类似的东西可以帮助我吗? 我正在使用 React。

这里有一个codesandbox

javascript css
1个回答
0
投票

您可以将布局存储在数组中。在下面的示例中,我创建了每个布局的压缩版本。

数字代表要跳过的单元格数量,“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>

© www.soinside.com 2019 - 2024. All rights reserved.