如果 DOM 是从 JS 构造的,如何在调整大小事件后重建

How to rebuild DOM after a resize event if it is being constructed from JS

我正在一个实施砖石画廊的项目中工作。 它工作得很好,但我需要在 JS 构造调用中动态调整列的数量...... 我已经尝试过不同的方法,包括调整大小事件、while 循环、条件 if,甚至从 CSS 使用 mediaQueries 来破解列号、陷入困境、递归调用和无限循环,但我找不到一个解决方案...

const masonryLayout = (containerElem, itemsElems, columns) => {

    // Crea Container para las columnas
    containerElem.classList.add('masonry-layout', `columns-${columns}`)

    // Crea n-columnas de acuerdo a "columns"
    let columnsElements = []
    for (let i = 1; i <= columns; i++) {
      let column = document.createElement('div')
      column.classList.add('masonry-column', `column-${i}`)
      containerElem.appendChild(column)
      columnsElements.push(column)
    }

    // Ubica cada imagen en la columna correspondiente
    for (let m = 0; m < Math.ceil(itemsElems.length / columns); m++) {
      for (let n = 0; n < columns; n++) {
        let item = itemsElems[m * columns + n]
        columnsElements[n].appendChild(item)
        item.classList.add('masonry-item')
      }
    }
}

masonryLayout(document.getElementById("gallery"), document.querySelectorAll(".gallery-item"),5)
.gallery-item img {
  max-width: 100%;
  display: block;
}
.masonry-layout {
  --columns: 5;
  --gap: 0.6rem;
  display: grid;
  grid-template-columns: repeat(var(--columns), 1fr);
  grid-gap: var(--gap);
}
.masonry-layout .masonry-item {
  margin-bottom: var(--gap);
}

.masonry-layout.columns-1 {
  --columns: 1;
}
.masonry-layout.columns-2 {
  --columns: 2;
}
.masonry-layout.columns-3 {
  --columns: 3;
}
.masonry-layout.columns-4 {
  --columns: 4;
}
.masonry-layout.columns-5 {
  --columns: 5;
}
<div class="gallery" id="gallery">
  <div class="columnNbrClass"></div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=100" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=200" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=300" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=400" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=500" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=600" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/400?image=700" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=800" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=900" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/480?image=925" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/550?image=950" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/600?image=1000" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=25" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=50" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=75" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=100" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=125" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=161" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/400?image=175" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=200" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=225" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/480?image=250" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/550?image=275" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/600?image=300" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=13" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=26" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=39" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=52" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=65" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=78" alt="" class="">
  </div>
</div>

基本上,我需要 masonryLayout 构造函数中的列号在调整大小时动态更改,但我找不到办法,我什至尝试保存原始 html 文档,但没有任何运气.. .如果有人有任何想法,很高兴听到和学习。

非常感谢您的交流!

不确定这是否是您想要的,但如果您只想要一个可调整大小的砖石画廊,您可以使用 js 来实现。如果您使用 js 动态添加项目,它也可以工作。

为了测试调整大小行为,只需在 fiddle 中调整输出面板的大小: JsFiddle Example

解释:

使用带最小宽度的媒体查询将随着 window 大小的增加而增加列数,其余的将由网格布局完成。使用 js 添加内容将强制浏览器重新呈现,因此这应该不是问题。

这是一个没有 js 的工作示例,只有 css:

.gallery-item img {
  max-width: 100%;
  display: block;
}
.masonry-layout {
  --columns: 1;
  --gap: 0.6rem;
  columns: var(--columns);
  grid-gap: var(--gap);
}
.masonry-layout .masonry-item {
  margin-bottom: var(--gap);
  display: inline-block;
}

@media only screen and (min-width: 300px) {
  .masonry-layout {
    --columns: 2;
  }
}

@media only screen and (min-width: 500px) {
  .masonry-layout {
    --columns: 3;
  }
}

@media only screen and (min-width: 800px) {
  .masonry-layout {
    --columns: 4;
  }
}

@media only screen and (min-width: 1000px) {
  .masonry-layout {
    --columns: 5;
  }
}
<div class="gallery masonry-layout" id="gallery">
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=100" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=200" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=300" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=400" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=500" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=600" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/400?image=700" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=800" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=900" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/480?image=925" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/550?image=950" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/600?image=1000" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=25" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=50" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=75" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=100" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=125" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=161" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/400?image=175" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=200" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=225" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/480?image=250" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/550?image=275" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/600?image=300" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/325?image=13" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/450?image=26" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/280?image=39" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/540?image=52" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/380?image=65" alt="" class="">
  </div>
  <div class="gallery-item">
    <img src="https://picsum.photos/450/300?image=78" alt="" class="">
  </div>
</div>

[编辑]

也看看这个fiddle 我使用了您的代码并对其进行了修改以在再次填充之前清除容器并添加了一个onresize,它似乎有效。 您的错误之一是没有清除所有已设置的 classes,因此在 column.classList.add('masonry-column',column-${i}); 中您添加了两个 classes,但最后一个add 仍然存在,因此当您使用 1 和 2 作为列参数调用方法 2 次时,您将具有以下 class 声明:

1:

class="masonry-column column-1"

2:

class="masonry-column column-1 column-2"

现在,当您缩小 window 时,第 2 列仍然存在,您将显示两列,但只有一列被填充。为了解决这个异常,我添加了 containerElem.className = '' 以在设置之前清除 class。

你的第二个问题是: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. 在你的情况下,你有 30 个项目,你尝试向每个列添加相同数量的项目,这适用于 1、2 和 3 列,因为 30 可以除以每个数字,但对于 4 这是不可能的并且即使在所有列之间也没有足够的项目来拆分它们。为防止错误,您可以检查是否还有剩余的项目:

if(m*columns + n >= itemsElems.length){
  continue;
}

Here 是更新后的 fiddle,两个错误都已修复。