Skip to content

Help implementing custom layout #51

@diegoaguilar

Description

@diegoaguilar

I've found myself with the following situation:

  • Items placed using pinterest layout are properly arranged. No overlapping, gutters correctly place and distributed
  • Items got an image and text
  • simple layout would just overlap / smash every item
  • I don't particularly need à la pinterest layout but every column starting a a common height

I tried to pass a custom layout overwriting the pinterest layout code.

I've got this:

import { chunk } from "lodash";

export default function(items, props) {
  const { columns, columnWidth, gutterWidth, gutterHeight } = props;

  const columnHeights = [];
  for (let i = 0; i < columns; i++) {
    columnHeights.push(0);
  }

  const positions = items.map(itemProps => {
    const column = columnHeights.indexOf(Math.min.apply(null, columnHeights));

    const height =
      itemProps.itemHeight || (itemProps.itemRect && itemProps.itemRect.height);

    if (!(height && typeof height === "number")) {
      throw new Error(
        'Each child must have an "itemHeight" prop or an "itemRect.height" prop.'
      );
    }

    const x = column * columnWidth + column * gutterWidth;
    const y = columnHeights[column];

    columnHeights[column] += Math.round(height) + gutterHeight;

    return [x, y];
  });

  const allHeights = items.map(itemProps => 
    itemProps.itemHeight || (itemProps.itemRect && itemProps.itemRect.height)
  );

  const chunkHeights = chunk(allHeights, columns);

  const gridWidth = columns * columnWidth + (columns - 1) * gutterWidth;
  const gridHeight = Math.max.apply(null, columnHeights);

  const rows = chunk(positions, columns);
  let previewRowYStart = 0;
  let previewRowYEnd = 0;
  const orderedPositions = rows.map((row: any, rowIndex) => {
    const columnsYPositions = row.map(([x, y]) => y);
    const max = Math.max(...columnsYPositions);
    let yPosition = max;
    if (rowIndex !== 0) {
      const overlap = previewRowYEnd >= max;
      if (overlap) yPosition = (max + (previewRowYEnd - max)) * 1.05;
    }

    previewRowYStart = rowIndex === 0 ? 0 : max;
    previewRowYEnd = max + Math.max(...chunkHeights[rowIndex] as number[]);

    return row.map(([ x ]) => [ x, yPosition ]);
  });

  return { positions: orderedPositions.flat(1), gridWidth, gridHeight };
}

Where basically I'm trying to order the item Y position into chunks according to their row, take the highest and set a common Y for all of them. Also I'd take previous row height and detect the chance of an overlap, adding some extra distance if overlapping.

This seems to work except that in some cases, the distance between rows is huge. I've tried to adjust the yPosition calculation when there's an overlap and also reduced the gutter but I can't get a consistent and logic result.

Any suggestions or directions would be appreciated

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions