具有网格布局的砌体画廊
Masonry gallery with grid layout
我一直在寻找带有网格布局的 Masonry 画廊,但没有找到所以我决定自己做。我使用带有网格布局的 customElement,但是当我动态分配网格行时我被阻止了。
我希望得到您的反馈并帮助改进它。
我检测到的一些错误是:
- 需要 运行 2 次才能工作
- 当 image/container 高度不是 100 的倍数时空格
HTML
<masonry-gallery></masonry-gallery>
JS
class MasonryGallery extends HTMLElement {
items = [
{ image:'https://unsplash.it/200/100/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/400/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/100/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/700/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/600/' },
{ image:'https://unsplash.it/200/100/' }
]
constructor() {
super()
this.attachShadow({ mode: 'open'})
this.create()
this.append()
}
create() {
this.style.display = 'grid'
this.style.gridTemplateColumns = 'repeat(auto-fill, 200px)'
this.style.gridTemplateRows = 'repeat(auto-fill, 1fr)'
this.style.gridGap = '1rem'
this.style.gridAutoFlow = 'row dense'
}
append() {
this.items.map(item => {
const div = document.createElement('DIV');
const image = document.createElement('IMG')
image.src = item.image
div.appendChild(image)
this.shadowRoot.appendChild(div)
div.style.gridRow = 'auto / span ' + [...String(image.height)][0]
})
}
}
customElements.define('masonry-gallery', MasonryGallery)
您的"bugs"有以下原因:
- 您尝试在图像附加到组件后立即计算图像的高度,但此时它的高度是未知的,只有在图像加载后才能知道。
- 网格行之间有 1rem (16px) 的间距,因此每张 100px 高的图像将网格高度增加 116px。
此行为可以修复,例如,通过对您的 append
方法进行以下编辑:
append() {
let gap = parseInt(getComputedStyle(this).gridRowGap)
this.items.map(item => {
const div = document.createElement('DIV');
const image = document.createElement('IMG')
image.style.display = 'block';
image.src = item.image
div.appendChild(image)
image.onload = function() {
this.parentNode.style.gridRow = 'auto / span ' + ((this.height + gap)/(100 + gap));
}
this.shadowRoot.appendChild(div)
})
}
并将gridRows
替换为gridAutoRows = '100px'
以使垂直节奏统一,并相应地调整图像的高度。
你可以看到结果in the edited Fiddle。
我一直在寻找带有网格布局的 Masonry 画廊,但没有找到所以我决定自己做。我使用带有网格布局的 customElement,但是当我动态分配网格行时我被阻止了。
我希望得到您的反馈并帮助改进它。
我检测到的一些错误是:
- 需要 运行 2 次才能工作
- 当 image/container 高度不是 100 的倍数时空格
HTML
<masonry-gallery></masonry-gallery>
JS
class MasonryGallery extends HTMLElement {
items = [
{ image:'https://unsplash.it/200/100/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/400/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/100/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/700/' },
{ image:'https://unsplash.it/200/300/' },
{ image:'https://unsplash.it/200/200/' },
{ image:'https://unsplash.it/200/600/' },
{ image:'https://unsplash.it/200/100/' }
]
constructor() {
super()
this.attachShadow({ mode: 'open'})
this.create()
this.append()
}
create() {
this.style.display = 'grid'
this.style.gridTemplateColumns = 'repeat(auto-fill, 200px)'
this.style.gridTemplateRows = 'repeat(auto-fill, 1fr)'
this.style.gridGap = '1rem'
this.style.gridAutoFlow = 'row dense'
}
append() {
this.items.map(item => {
const div = document.createElement('DIV');
const image = document.createElement('IMG')
image.src = item.image
div.appendChild(image)
this.shadowRoot.appendChild(div)
div.style.gridRow = 'auto / span ' + [...String(image.height)][0]
})
}
}
customElements.define('masonry-gallery', MasonryGallery)
您的"bugs"有以下原因:
- 您尝试在图像附加到组件后立即计算图像的高度,但此时它的高度是未知的,只有在图像加载后才能知道。
- 网格行之间有 1rem (16px) 的间距,因此每张 100px 高的图像将网格高度增加 116px。
此行为可以修复,例如,通过对您的 append
方法进行以下编辑:
append() {
let gap = parseInt(getComputedStyle(this).gridRowGap)
this.items.map(item => {
const div = document.createElement('DIV');
const image = document.createElement('IMG')
image.style.display = 'block';
image.src = item.image
div.appendChild(image)
image.onload = function() {
this.parentNode.style.gridRow = 'auto / span ' + ((this.height + gap)/(100 + gap));
}
this.shadowRoot.appendChild(div)
})
}
并将gridRows
替换为gridAutoRows = '100px'
以使垂直节奏统一,并相应地调整图像的高度。
你可以看到结果in the edited Fiddle。