检测 div 网格中的间隙

Posted

技术标签:

【中文标题】检测 div 网格中的间隙【英文标题】:Detecting gaps in grid of divs 【发布时间】:2012-12-04 14:45:27 【问题描述】:

编辑 已找到解决方案!

这是blog post,这是Github repo!

我正在创建一个由多个大小的框组成的 div 网格,这些大小是设置的高度和宽度 - 但是是动态生成的,因此每次加载页面时都会有一个不同的网格。

我的问题 - 我尝试使用 Masonry,但最终留下了空隙,还尝试了同位素。我目前正在浮动导致布局中断的元素。

它是如何构建的 - 我计算屏幕尺寸并确定从 1 到 6 的页面的最佳列数,然后根据该列宽我计算一个“块”,这个块基本上是完美的网格。然后我循环遍历我的元素并为它们提供 1x1、1x2、2x2 尺寸。

这里是另一个随机生成的网格供参考

我的问题 - 有没有一种很好的方法来检测丢失的空间 - 目前我将红色和黑色的盒子放在另一个绿色的“块”网格上,让我看看我在哪里丢失了空间。我已经阅读了有关背包包装问题以及垃圾箱包装问题的信息——我很难理解其中任何一个问题。

我尝试过的 - 我试图在放置块以确定最佳尺寸时进行计算,但这仍然会导致奇怪的行为。我也尝试过使用砖石和同位素。

底部边缘参差不齐,但实际网格不能包含任何间隙。

注意 - 网格可能由无限数量的元素组成 - 我一直在考虑是否要从底部区域获取并复制一个元素并将其放置到我可以的缺失区域中避免不得不“转移”元素——我只需要知道如何找到那个缺失的空间。

任何帮助或指出正确的方向都会很棒!

这是jsfiddle

这里是js的基本代码...

    (function() 
    GRID = function(el, sel) 
        var self = this,
            ran, ranSize, h, w;

        self.options = 
            el: $(el),
            sel: $(sel),
            cols: 1,
            block: 
                height: 0,
                width: 0
            ,
            matrix: 
                w: [],
                h: [],
                t: [],
                l: []
            ,
            row: 
                height: 0,
                width: 0
            ,
            col: 
                height: 0,
                width: 0
            
        ;

/*
         * Size array
        */
        self.sizes = [];
        self.sizes[0] = [2, 2];
        self.sizes[1] = [1, 2];
        self.sizes[2] = [1, 1];



        self.setup = function() 

/*
             * Setup all options 
            */
            // block size
            self.options.block.height = (window.innerWidth / self.cols()) / 1.5;
            self.options.block.width = (window.innerWidth / self.cols());

            // row
            self.options.row.width = window.innerWidth;


            for (var i = 0; i < 60; i++) 
                $(".grid").append('<div class="box"></div>');
            

            self.size_boxes();


        
        self.size_boxes = function() 

            if (self.cols() == 1) 
                self.options.sel.height(self.options.block.height);
                self.options.sel.width(self.options.block.width);
            
            else 
                self.options.sel.each(function() 

                    $this = $(this);

                    ran = Math.floor(Math.random() * self.sizes.length);
                    ranSize = self.sizes[ran];

                    if ($this.hasClass('promoted')) 
                        ran = 0;
                    
                    if ($this.hasClass('post')) 
                        ran = 2;
                    
                    h = self.options.block.height * self.sizes[ran][6];
                    w = self.options.block.width * self.sizes[ran][0];

                    // box sizes
                    $this.height(h);
                    $this.width(w);
                );
            
            $(".grid .box").height(self.options.block.height);
            $(".grid .box").width(self.options.block.width);
        
        self.cols = function() 
/*
             * Determine cols
            */
            var w = Math.floor(window.innerWidth);
            var cols = 0;

            if (w < 480) 
                cols = 1;
            
            else if (w > 480 && w < 780) 
                cols = 2;
            
            else if (w > 780 && w < 1080) 
                cols = 3;
            
            else if (w > 1080 && w < 1320) 
                cols = 4;
            
            else if (w > 1320 && w < 1680) 
                cols = 5
            
            else 
                cols = 6;
            
            return cols;
        
        self.resize = function() 
            $(".grid").height(window.innerHeight);
            self.options.block.height = (window.innerWidth / self.cols()) / 1.5;
            self.options.block.width = (window.innerWidth / self.cols());

            self.options.row.width = window.innerWidth;

            self.size_boxes();
        

        self.setup();
        return self;

    ;
)();
var _GRID = new GRID('.gallery', '.box');​

【问题讨论】:

嘿,伙计,我试图解决这个问题,但我完全被你的问题弄糊涂了......“将红色和黑色的盒子放在另一个网格上”真的让我很震惊,也,我不知道您是统一分配尺寸(1x1、1x2、2x2)还是每个块都有不同的尺寸,但也许这只是我的头:) 哈哈 - 所以我有两个绝对定位的 div。 1 网格是完美的框或“块”,这些块的尺寸是根据列数和屏幕宽度计算的。这是绿色网格(主要是为了让我看看空白在哪里发生)。现在另一个网格是我的元素将被调整大小的地方。这些被告知占用“块”的 1x1、1x2 和 2x2 的空间,因此 1 块宽,2 块高。您在图像中看到的黑色和红色是尺寸元素,绿色是显示要占用的空间尺寸的基本块...... 你想创建这样的东西吗:stackexchange.com/sites 这可能无法帮助我找到解决方案,但每个盒子的尺寸是流动的还是固定的?例如,如果您使用 6 列,则基本网格块宽度是 16.66% 吗?或者您是否根据窗口大小将其设置为像素宽度?比如 280px 如果你的窗口是 1680px 宽。 @inorganik 是的类似 - 这是使用同位素 - 好奇他们使用什么布局方法...... 【参考方案1】:

我会使用内存中的布尔值矩阵来跟踪您的“完美网格”。这个矩阵存储空间是否被填充。每当您放置其中一个框时,您都会计算哪些方格被占用并更新您的矩阵。

【讨论】:

这与我一直在考虑做的事情非常接近,我被一排排地想着它们……会不会是矩阵[0] = [true,true,true,假],矩阵[1] = [真,真,假,假]?假设这是一个 4 列网格 这是一个棘手的问题!您是否还需要逻辑来根据 float:left 的性质计算矩阵布尔值? 是的,但您不必将它们排成一行。根据您的矩阵格式,您可以将它们一一设置,例如 matrix[row][column] = true 或 matrix[column][row] = false。 接受您的回答,因为您为我指明了正确的方向 :) 谢谢!【参考方案2】:

如果您将它们放在列中,只需将 div 放在列中。例如,如果您确定应该有 4 列:

<div>
    <div>Column 1, Div 1</div>
    <div>Column 1, Div 2</div>
    <div>Column 1, Div 3</div>
    <div>Column 1, Div 4</div>
</div>
<div>
    <div>Column 2, Div 1</div>
    <div>Column 2, Div 2</div>
    <div>Column 2, Div 3</div>
    <div>Column 2, Div 4</div>
</div>
<div>
    <div>Column 3, Div 1</div>
    <div>Column 3, Div 2</div>
    <div>Column 3, Div 3</div>
    <div>Column 3, Div 4</div>
</div>
<div>
    <div>Column 4, Div 1</div>
    <div>Column 4, Div 2</div>
    <div>Column 4, Div 3</div>
    <div>Column 4, Div 4</div>
</div>

当然,这只有在每列中的 div 高度相等时才有效。

【讨论】:

可能是的 - 问题是它们的高度和宽度不同。这可能意味着一列可能包含 4 个元素,而另一列包含 5 个试图填充该区域。

以上是关于检测 div 网格中的间隙的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 列网格间隙

如何处理 Bootstrap 3 列没有间隙?

如何减少网格中列之间的间隙

文本输入填充与父容器的网格间隙重叠[重复]

如何在第二个 Tailwind CSS 网格列中左对齐内容,使其在所有屏幕尺寸下都保持与第一列之间的间隙?

Bootstrap 缩略图网格中额外项目之间的间隙