首页 > 解决方案 > 如果它是从 JS 构建的,如何在调整大小事件后重建 DOM

问题描述

我正在一个实施砖石画廊的项目中工作。它工作得很好,但我需要在 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 文档但没有任何运气......如果有人有任何想法,它会很高兴听到和学习。

非常感谢您的交流!

标签: htmlcssrebuildonresizepure-js

解决方案


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

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

解释:

使用带有 min-width 的媒体查询将随着窗口大小的增加而增加列数,其余的将由网格布局完成。用 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>

[编辑]

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

1:

class="masonry-column column-1"

2:

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

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

您的第二个问题是: 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;
}

是一个更新的小提琴,修复了两个错误。


推荐阅读