javascript — Blok galerii murarskich działa w edytorze bloków, ale nie w edytorze szablonów
![javascript — Blok galerii murarskich działa w edytorze bloków, ale nie w edytorze szablonów](https://oen.pl/wp-content/uploads/2023/09/apple-touch-icon@2.png)
Buduję niestandardowy blok galerii Masonry (wersja inna niż jQuery) i udało mi się sprawić, by działał w edytorze bloków. Używam WP 6.3. To jest mniej więcej kod:
JS:
const containerRef = useRef(null);
const {
attributes: { items, columns, gap },
setAttributes,
} = props;
useEffect(() => {
var msnry;
if (containerRef.current) {
imagesLoaded(containerRef.current, function () {
msnry = new Masonry(containerRef.current, {
itemSelector: '.gallery-item',
columnWidth: '.grid-sizer',
percentPosition: true,
gutter: parseInt(gap),
});
});
}
return () => {
msnry?.destroy();
}
}, [items, columns, gap]);
....
const displayItems = (items) => {
return (
items.map((item, index) => {
return (
<div className="gallery-item" key={index}>
<figure>
<img className={`wp-image-${item.id}`} src={item.url} alt={item.alt} key={item.id} />
</figure>
</div>
)
})
)
};
{items.length > 0 ?
<div {...blockProps}>
<div className="gallery-items" style={{ '--gap': gap }} ref={containerRef}>
<div className="grid-sizer"></div>
{displayItems(items)}
</div>
</div>
}
SCSS:
.wp-block-my-masonry-gallery {
.gallery-items {
--gap: 10px;
display: flex;
flex-wrap: wrap;
gap: var(--gap);
}
@for $i from 2 through 8 {
&.columns-#{$i} {
.gallery-item,
.grid-sizer {
width: calc(percentage(math.div(1, $i)) - var(--gap) + (var(--gap) / $i));
}
}
}
}
blok.json
{
"apiVersion": 3,
"name": "my/masonry-gallery",
"title": "My Masonry Gallery",
"attributes": {
"items": {
"type": "array",
"default": []
},
"columns": {
"type": "number",
"minimum": 1,
"maximum": 8,
"default": 3
},
"gap": {
"type": "string",
"default": "10px"
}
},
"editorScript": [
"file:./index.js",
"imagesloaded",
"masonry"
],
"viewScript": [
"file:./view.js",
"imagesloaded",
"masonry"
],
"style": [
"file:./style-index.css",
"file:./view.css"
],
"editorStyle": "file:./index.css"
}
Jak powiedziałem wcześniej, blok działa w edytorze bloków, ale kiedy próbuję tego w nowym edytorze szablonów FSE, biblioteka Masonry nie jest poprawnie inicjowana, ponieważ wysokość kontenera Masonry jest ustawiona na zero, w związku z czym obrazy galerii nakładają się kolejne bloki na ekranie.
Blok w edytorze bloków:
Zablokuj w edytorze szablonów FSE:
Ktoś wskazał mi następujący post, który wspomina, że edytor szablonów jest ładowany w ramce iframe, aby odizolować go od reszty ekranu administracyjnego i może powodować problemy z bibliotekami innymi niż React i sugerować pewne zmiany, aby działały w edytorze iframe:
Dokonałem refaktoryzacji kodu, korzystając z przykładów w poście, ale otrzymuję takie same wyniki jak poprzednio:
const containerRef = useRefEffect((element) => {
var msnry;
imagesLoaded(element, function () {
msnry = new Masonry(element, {
itemSelector: '.gallery-item',
columnWidth: '.grid-sizer',
percentPosition: true,
gutter: parseInt(gap),
});
});
return () => {
msnry?.destroy();
}
}, [items, columns, gap]);
Kierując się sugestiami @stokesman, bez powodzenia dokonałem refaktoryzacji kodu do następującego:
const containerRef = useRefEffect((element) => {
var msnry;
const { ownerDocument } = element;
const { defaultView } = ownerDocument;
if ( ! defaultView.imagesLoaded || ! defaultView.Masonry ) {
return;
}
defaultView.imagesLoaded(element, function () {
msnry = new defaultView.Masonry(element, {
itemSelector: '.gallery-item',
columnWidth: '.grid-sizer',
percentPosition: true,
gutter: parseInt(gap),
});
});
return () => {
msnry?.destroy();
}
}, [items, columns, gap]);
The if ( ! defaultView.imagesLoaded || ! defaultView.Masonry )
sprawdzenie nigdy nie daje wartości false
a część murowana nigdy nie jest wykonywana.
Jakieś pomysły?
AKTUALIZACJA (20.02.2024):
Aby wstawić skrypty załadowane masonry i obrazami do elementu iframe, tak aby można było z nich korzystać z poziomu elementu iframe, należy je dodać do script
podpora (nie editorScript
rekwizyt) w block.json
plik. W przeciwnym razie z jakiegoś powodu są ładowane POZA ramką iframe.
...
"script": [
"imagesloaded",
"masonry"
],
"editorScript": "file:./index.js",
"viewScript": "file:./view.js",
...