PHPackages                             reallifekip/grid-map - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. reallifekip/grid-map

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

reallifekip/grid-map
====================

A lightweight grid-based area mapping library for defining rectangular regions in a cell grid.

v1.1.1(1mo ago)019MITPHPPHP ^8.0

Since Sep 4Pushed 1mo agoCompare

[ Source](https://github.com/ReallifeKip/GridMap)[ Packagist](https://packagist.org/packages/reallifekip/grid-map)[ RSS](/packages/reallifekip-grid-map/feed)WikiDiscussions main Synced today

READMEChangelog (3)Dependencies (1)Versions (4)Used By (0)

GridMap
=======

[](#gridmap)

**Language:** English | [繁體中文](README.zh-TW.md)

A lightweight PHP micro-library for **grid slicing**. It divides a fixed-size plane (e.g., 1920×1080 canvas, video wall, media composition, dashboard, or layout system) into a grid according to specified proportions, then sequentially "fills" rectangular slices into available cells and returns their pixel coordinates and sizes.

`GridMap` uses a simple row-major first-fit scanning algorithm to find the first available area that can fit a slice of the requested column/row span. If successful, the area is marked as occupied and the next slice is processed. If a slice cannot fit, or if the grid is not fully occupied at the end, an exception is thrown.

---

✨ Features Overview
-------------------

[](#-features-overview)

- ✅ Single static class, easy to understand and integrate
- ✅ Pure PHP ≥ 8.0 with typed, immutable DTOs
- ✅ Define slices in "grid units" and automatically convert to pixel coordinates `x, y, width, height`
- ✅ Deterministic first-fit placement, reproducible results
- ✅ Uses integer division `intdiv` to avoid floating-point rounding errors
- ✅ Automatically detects unplaceable or unfilled slices and throws clear exceptions
- ✅ Suitable for dynamic layouts, video walls, auto-layout suggestions

---

📦 Installation
--------------

[](#-installation)

```
composer require reallifekip/grid-map
```

---

🚀 Quick Start
-------------

[](#-quick-start)

```
use ReallifeKip\GridMap\GridMap;
use ReallifeKip\GridMap\Objects\DTOs\Config;

// Canvas: 1920×1080, divided into a 24×12 grid (typical 16:9 split)
$result = GridMap::slice(
    Config::fromArray([
        'imageWidth'  => 1920,
        'imageHeight' => 1080,
        'columns'     => 24,
        'rows'        => 12,
        'cells'       => [
            ['colSpan' => 6, 'rowSpan' => 6],
            ['colSpan' => 6, 'rowSpan' => 6],
            ['colSpan' => 6, 'rowSpan' => 6],
            ['colSpan' => 6, 'rowSpan' => 6],
            ['colSpan' => 12, 'rowSpan' => 6],
            ['colSpan' => 12, 'rowSpan' => 6],
        ],
    ])
);

print_r($result);
```

Example output:

```
Array
(
    [0] => Slice Object ( [x] => 0    [y] => 0    [width] => 480  [height] => 540 )
    [1] => Slice Object ( [x] => 480  [y] => 0    [width] => 480  [height] => 540 )
    [2] => Slice Object ( [x] => 960  [y] => 0    [width] => 480  [height] => 540 )
    [3] => Slice Object ( [x] => 1440 [y] => 0    [width] => 480  [height] => 540 )
    [4] => Slice Object ( [x] => 0    [y] => 540  [width] => 960  [height] => 540 )
    [5] => Slice Object ( [x] => 960  [y] => 540  [width] => 960  [height] => 540 )
)

```

> Width/height are actual pixels, calculated via `intdiv`. For example: `1920/24 = 80`, `1080/12 = 90`. A 6-column span = 6 × 80 = 480 px; a 6-row span = 6 × 90 = 540 px.

---

🧠 Core Concept
--------------

[](#-core-concept)

TermDescription`imageWidth`, `imageHeight`Total canvas size (pixels)`columns`, `rows`Number of grid divisions (horizontal / vertical)`Cell` `colSpan`, `rowSpan`Slice rectangle defined in grid units, not pixelsreturn `Slice[]`Each placed slice object with `x`, `y`, `width`, `height` (px)### Config defaults

[](#config-defaults)

PropertyDefault`imageWidth``2500``imageHeight``1686``columns``24``rows``12`Steps (simplified):

1. Compute all grid line coordinates: `cols[x] = intdiv(x * imageWidth, columns)`, `rows[y] = intdiv(y * imageHeight, rows)`
2. Use a 1D array to mark whether each cell is occupied
3. For each `Cell`:
    - Scan row-major for the first fitting location
    - Check that all covered cells are free
    - Mark occupied and convert to a pixel `Slice`
4. Throw `\Exception` if a cell cannot be placed
5. Throw `\Exception` if the grid is not fully occupied after all cells are placed

---

✅ Example Use Cases
-------------------

[](#-example-use-cases)

Use CaseDescriptionMedia/Video wallAutomatically arrange multiple video sourcesVideo compositingMap multiple tracks into fixed canvas coordinatesRealtime dashboardAuto-generate initial layouts for widget cardsGame/Level editorPlan map or scene block placementsAd screen layoutPlace multiple ad creatives into grid layout---

🛠️ Advanced Example: Mixed Sizes &amp; Error Handling
-----------------------------------------------------

[](#️-advanced-example-mixed-sizes--error-handling)

```
use ReallifeKip\GridMap\GridMap;
use ReallifeKip\GridMap\Objects\DTOs\Config;

try {
    $result = GridMap::slice(
        Config::fromArray([
            'imageWidth'  => 1200,
            'imageHeight' => 800,
            'columns'     => 20,
            'rows'        => 10,
            'cells'       => [
                ['colSpan' => 4,  'rowSpan' => 4], // A
                ['colSpan' => 8,  'rowSpan' => 4], // B
                ['colSpan' => 8,  'rowSpan' => 4], // C — must fully fill the grid
                ['colSpan' => 20, 'rowSpan' => 6], // D
            ],
        ])
    );
} catch (\Exception $e) {
    // Thrown if a slice cannot be placed, or if the grid is left partially unfilled
    echo 'Slice failed: ' . $e->getMessage();
}
```

---

⚠️ Notes
--------

[](#️-notes)

1. Each `Cell` must have two positive integers: `colSpan` and `rowSpan`
2. `colSpan` cannot exceed `columns`; `rowSpan` cannot exceed `rows`
3. Strategy is "first feasible placement": not optimized for space, just deterministic
4. For "optimal packing / rotation / reordering", preprocess cells (e.g., sort by size)
5. The returned `Slice[]` array indexes correspond 1-to-1 with the input `cells` order
6. All cells **must** collectively fill the entire grid — a partially filled grid throws an `\Exception`

---

🔍 Return Data Format
--------------------

[](#-return-data-format)

Returns an array of `Slice` objects:

```
/** @var ReallifeKip\GridMap\Objects\DTOs\Slice[] $result */
$result[0]->x;      // int — left edge in pixels
$result[0]->y;      // int — top edge in pixels
$result[0]->width;  // int — width in pixels
$result[0]->height; // int — height in pixels
```

---

🧪 Testing Suggestions
---------------------

[](#-testing-suggestions)

You may write PHPUnit tests to verify:

- Slice count matches returned array count
- No overlapping rectangles (check cell intersections)
- When all cells fit, occupied grid count = `columns * rows`
- Oversized cells trigger `\Exception`
- Partially filled grids trigger `\Exception`

---

📄 License
---------

[](#-license)

This package uses the [MIT License](./LICENSE) – Free for commercial use / modification / distribution, just keep copyright notice.

---

👤 Developer Info
----------------

[](#-developer-info)

Author: Kip () GitHub: [@ReallifeKip](https://github.com/ReallifeKip)

If this project helps you: feel free to Star, share, or suggest improvements!

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance88

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~123 days

Total

3

Last Release

59d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/91828793?v=4)[Kip](/maintainers/ReallifeKip)[@ReallifeKip](https://github.com/ReallifeKip)

---

Top Contributors

[![ReallifeKip](https://avatars.githubusercontent.com/u/91828793?v=4)](https://github.com/ReallifeKip "ReallifeKip (6 commits)")

---

Tags

gridgridmapgrid-map

### Embed Badge

![Health badge](/badges/reallifekip-grid-map/health.svg)

```
[![Health](https://phpackages.com/badges/reallifekip-grid-map/health.svg)](https://phpackages.com/packages/reallifekip-grid-map)
```

###  Alternatives

[desandro/masonry

Cascading grid layout library

16.7k436.4k4](/packages/desandro-masonry)[nicolaskruchten/pivottable

Javascript Pivot Table (aka Pivot Grid, Pivot Chart, Cross-Tab) implementation with drag'n'drop.

4.4k219.4k1](/packages/nicolaskruchten-pivottable)[kartik-v/yii2-grid

Yii 2 GridView on steroids. Various enhancements and utilities for the Yii 2.0 GridView widget.

5546.9M182](/packages/kartik-v-yii2-grid)[maxazan/jquery-treegrid

jquery treegrid plugin

55754.6k](/packages/maxazan-jquery-treegrid)[codenco-dev/nova-grid-system

A Laravel Nova tool to have a grid system

81357.7k](/packages/codenco-dev-nova-grid-system)[himiklab/yii2-sortable-grid-view-widget

Sortable modification of standard Yii2 GridView widget

79361.2k7](/packages/himiklab-yii2-sortable-grid-view-widget)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
