You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript矩形打包算法如何实现flex justify-content:space-between两端对齐

更优实现方案(基于业务约束定制,无需二次遍历修正)

你的场景有三个强约束,完全不需要用通用二叉树装箱算法的逻辑,直接在行划分阶段就计算对齐参数,一次布局即可完成:

核心思路

利用所有矩形高度一致、宽度为固定列宽整数倍的特性,采用行优先布局逻辑,直接在分配坐标时带入两端对齐的偏移计算:

  • 遍历所有待打包矩形时先按行聚合:累加当前行矩形总宽度,直到加入下一个矩形会超出画布宽度,即完成当前行的划分
  • 计算当前行两端对齐所需的均匀间距:行总空隙 = 画布宽度 - (当前行所有矩形宽度和 + 预设gutter * (当前行矩形数量 - 1)),单段额外间距为 行总空隙 / (当前行矩形数量 - 1)
  • 直接按计算出的总间距分配当前行每个矩形的x、y坐标,y坐标固定为 行序号 * (矩形高度 + gutter),x坐标按前一个矩形的x+宽度+gutter+单段额外间距累加即可
  • 继续处理下一行,整个过程仅需一次遍历完成所有矩形坐标分配,效率远高于通用装箱算法

沿用现有Packer类的最小改动方案

如果不想换掉现有逻辑,也可以通过修改splitNode的右节点分配规则实现,不需要后续二次遍历:
因为所有矩形高度一致,每行的y坐标是固定值,每次检测到换行(即findNode命中了down节点)时,计算上一行的总空隙,直接修改上一行所有矩形的x坐标即可,改动量极小。

优化后适配两端对齐的Packer代码示例

export interface Block {
  w: number;
  h: number;
  fit?: Node;
}

export interface Node {
  x: number;
  y: number;
  w: number;
  h: number;
  used?: boolean;
  down?: Node;
  right?: Node;
}

export class JustifiedPacker {
  readonly w: number;
  readonly h: number;
  readonly root: Node;
  readonly gutter: number;
  // 存储当前行的所有块
  #currentLineBlocks: Block[] = [];
  // 当前行累计宽度
  #currentLineWidth = 0;
  // 当前行y坐标
  #currentY = 0;
  // 固定块高(约束所有块高度一致)
  readonly #blockHeight: number;

  constructor(w: number, h: number, blockHeight: number, gutter?: number) {
    this.w = w;
    this.h = h;
    this.gutter = gutter ?? 5;
    this.#blockHeight = blockHeight + this.gutter;
    this.root = { x: 0, y: 0, w: w, h: h, used: false };
  }

  fit(blocks: Block[]): void {
    for (const block of blocks) {
      const rawW = block.w + this.gutter;
      // 判断加入当前行是否超限
      if (this.#currentLineWidth + rawW > this.w && this.#currentLineBlocks.length > 0) {
        // 计算当前行的对齐偏移
        this.#adjustCurrentLine();
        // 换行重置
        this.#currentLineBlocks = [];
        this.#currentLineWidth = 0;
        this.#currentY += this.#blockHeight;
      }
      // 加入当前行
      this.#currentLineBlocks.push(block);
      this.#currentLineWidth += rawW;
      // 临时赋值坐标
      block.fit = {
        x: this.#currentLineWidth - rawW,
        y: this.#currentY,
        w: rawW,
        h: this.#blockHeight,
        used: true
      }
    }
    // 处理最后一行
    if (this.#currentLineBlocks.length > 0) {
      this.#adjustCurrentLine();
    }
  }

  // 计算当前行两端对齐的偏移,更新所有块的x坐标
  #adjustCurrentLine(): void {
    const blockCount = this.#currentLineBlocks.length;
    if (blockCount <= 1) return; // 单个块无需调整
    const totalGap = this.w - this.#currentLineWidth;
    const perGap = totalGap / (blockCount - 1);
    let offsetX = 0;
    for (let i = 0; i < blockCount; i++) {
      const block = this.#currentLineBlocks[i];
      if (block.fit) {
        block.fit.x = offsetX;
        offsetX += block.fit.w + perGap;
      }
    }
  }
}

export default JustifiedPacker;

内容的提问来源于stack exchange,提问作者ANimator120

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:27:01