Ik had achtergronden nodig met behangpatronen die je naadloos naast elkaar kunt plakken zoals bijvoorbeeld deze:


Er genoeg voorbeelden te vinden als je zoekt op iets als ‘seamless pattern images’. Als de licentie het toestaat, kun je ze als achtergrond gebruiken van bijvoorbeeld een Gutenberg Groupblock of Coverblock. (In de instellingsdialogen voor de achtergrond van deze blokken kun je aangeven dat de afbeelding niet moet worden opgerekt maar als tegels vullend naast elkaar gelegd, resulterend in daartoe strekkende CSS background-size en background-repeat regels).
Dit soort patronen wil je naar eigen smaak aanpassen: kleur, lijndikte, vorm, omvang van het herhaalde basiselement, etc. Je kunt natuurlijk ook zelf iets tekenen/maken in bijvoorbeeld Illustrator of Inkscape (die laatste heeft de voorkeur ivm de opvattingen over geestelijk eigendom die Adobe zijn gebruikers laat onderschrijven). Er zijn ook online generatoren te vinden die dit soort patronen voortbrengen (voeg de woorden ‘online generator’ toe bij het zoeken).
Hoe dan ook zou het beter zijn als je deze functionaliteit binnen de WordPress blockeditor hebt. Dan hoef je niet steeds te schakelen tussen de generator en WordPress en je hoeft niet steeds patronen te down- en uploaden ( en daarbij eventueel nog exporteren naar een bruikbaar formaat). Hiermee zou je bovendien de gebruiker die dit allemaal te omslachtig vindt van dienst kunnen zijn als deze nieuwe of aangepaste patronen nodig heeft.
Wat dus eigenlijk wenselijk is, is zo’n online svg-patroongenerator, maar dan als onderdeel van de Gutenberg editor. Om dit te bereiken doorliep ik een aantal stappen waarbij ik om te beginnen uitging van onderstaand achtergrond-patroon:
Het patroon op de achtergrond van dit venster heet Asanoha in Japan, wat hennep betekent. Het lijkt eigenlijk niet op een hennepblad maar dat maakt het niet minder fraai. En trouwens, wie ziet er nou twee vissen in het gelijknamige sterrenbeeld?
Met dit patroon in gedachten doorliep ik de volgende acht stappen:
- SVG Maken
- JSON maken
- JSON doorgeven aan Block Editor
- Extra functies toevoegen
- Inspector Controls toevoegen aan de block-editor
- Renderer maken met template, parameters en functie-resultaten
- Voorinstellingen
- SVG in de achtergrond van het blok plaatsen
Ten slotte maakte ik wat extra patronen met verschillende voorinstellingen van de parameters. Aan het eind staat daarvan een overzicht.
1. SVG Maken
Het Asanoha patroon is een herhaling in horizontale en verticale richting van de volgende basisfiguur:

De onderste helft is hierin dan weer het spiegelbeeld van de bovenste.
De afmetingen worden bepaald door slechts 1 parameter: de breedte. De hoogte is √3 x de breedte.
Daarnaast kun je variëren in lijndikte, lijnkleur en vulkleur en die komen dus als te wijzigen parameter in aanmerking.
Hieronder staat de SVG met een breedte van 80px, een lijndikte van 2px, #FFFFFF als lijnkleur en #000000 als achtergrondkleur:
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="139" viewBox="0 0 80 139" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg_bg">
<defs>
<path style="fill:none;" id="asanoha-base"
d="M 0,0 80,0 M 0,69.28 80,69.28 40,0 Z M 0,69.28 40,46.18 80,69.28 M 40,46.18 40,0 M 0,69.28 0,23.09 40,0 M 80,69.28 80,23.09 40,0" />
<pattern id="asanoha-pattern" patternUnits="userSpaceOnUse" width="80" height="138.56">
<use href="#asanoha-base" x="0" y="0" />
<use href="#asanoha-base" x="0" y="0" transform="scale(1,-1)" transform-origin="40 69.28"/>
</pattern>
</defs>
<rect id="bg" width="80" height="139" fill="#000000" />
<rect id="main" width="80" height="139" fill="url(#asanoha-pattern)" />
</svg>
2. JSON aanmaken
Om de waarde van de parameters te kunnen aanpassen in de WP block-editor, maakte ik een JSON object dat aan de block-editor kan worden doorgegeven. Hierin worden de parameters gespecificeerd en ook wordt hierin deze svg als een template doorgegeven zodat de block-editor van parameters en template samen een svg kan maken.
De templates waren vooralsnog zo eenvoudig dat een aparte template-engine eigenlijk niet nodig leek. Ik maakte een simpele renderfunctie die met een enkele regular expression parameter-waarden afkomstig van de block-editor in de template kon plaatsen. Niet uit sluiten valt dat in een later stadium gebruik van een wat geavanceerder template-engine de moeite waard zal blijken te zijn.
Om later nieuwe patronen toe te voegen, plaatste ik het JSON object in een bestand in een aparte map in de plugin directory: svg-tpl.
Zie: svg-tpl/ op Github
3. JSON doorgeven aan Block Editor
Het WP plugin bestand svg-bg.php leest alle bestanden in de template-map en geeft de JSON objecten in een array aan de block-editor door.
function get_svgs(){
$svgs = array();
$files = scandir( plugin_dir_path( __FILE__ ) . 'svg-tpl' );
foreach( $files as $file ){
if( $file == '.' || $file == '..' ) continue;
$file_info = pathinfo($file);
if ($file_info['extension'] !== 'json') continue;
$svg_json = json_decode( file_get_contents( plugin_dir_path( __FILE__ ) . 'svg-tpl/' . $file ) );
if( $svg_json->template === "file") {
$svg_json->template = file_get_contents( plugin_dir_path( __FILE__ ) . 'svg-tpl/' . $svg_json->name . '.svg' );
}
$svgs[] = $svg_json;
}
return $svgs;
}
function wp_svg_bg_enqueue_block_editor_assets() {
global $wp_scripts;
$svgs = get_svgs();
// Localize the script with the SVG objects
wp_localize_script('create-block-svg-bg-editor-script', 'svgObjects', $svgs);
}
add_action('enqueue_block_editor_assets', 'wp_svg_bg_enqueue_block_editor_assets');
Zie: svg-bg.php op Github
4. Functies toevoegen om te rekenen met parameters
De Blockeditor beschikt nu over een specificatie van de parameters en een template voor de SVG. Maar om de SVG te kunnen maken, moeten behalve de parameters ook hier en daar waarden kunnen worden gebruikt die van die parameters worden afgeleid. Zoals gezegd is bijvoorbeeld de hoogte van Asanoha-svg gelijk aan √3 * dx ( de breedte parameter ).
Daarom wordt aan de block-editor ook een property met javascript functies doorgegeven. In het geval van de hoogte van het Asanoha basiselement wordt de functie view.fuctions.svg_height doorgegeven waarmee de hoogte op basis van dx kan worden bepaald. Bij het evalueren van de functie wordt het geheele json-object ook zelf doorgegeven als parameter ‘data’ zodat de functie toegang heeft tot alle parameters in het JSON object:
{ "view ": {
"parameters" : {
...
},
"functions" : {
"svg_height": { "return Math.round( data.dx.value * Math.sqrt(3));" }
...
}
}
In het bestand svg-tpl/asanoha.json is het geheel te zien waarmee de blockeditor een op maat gemaakte svg moet kunnen genereren.
Zie: svg-tpl/asanoha.json op Github
5. Inspector Controls toevoegen aan de Block-editor
Nu het JSON object duidelijk kan maken welke Inspector controls kunnen worden ingesteld, kan de edit-block functie worden gemaakt.
Hierin wordt als eerste een selectbox gevuld met als opties de namen van alle json bestanden die er in de map svg-tpl zijn gevonden. Ik begon met alleen ‘Asanoha’ maar het is uitdrukkelijk de bedoeling dat er een aantal andere bijkomen. Op basis van het in deze selectbox geselecteerde json object worden vervolgens controls toegevoegd aan het panel in de Gutenberg Inspector controls. De parameter ‘dx’, zoals die in asanoha.json wordt gedefinieerd, heeft als type ‘range’. Dit betekent dat de edit-functie een RangeControl aan het panel toevoegt. Andere properties van ‘dx’ worden gebruikt om de RangeControl nader in te stellen, bijvoorbeeld minimum en maximum waarde.
Behalve het type ‘range’ herkent edit.js op dit moment de types ‘string’, ‘select’ en ‘colorpanel’. Daarmee kunnen overeenkomstige controls worden toegevoegd. Als het type niet herkend wordt, wordt het genegeerd.
Zie: src/edit.js op Github
6. Renderer maken voor template, parameters en functieresultaten
Als de benodigde parameters zijn ingesteld kan met de functie renderTemplate de uiteindelijke svg worden gegenereerd. Aanvankelijk leek een template engine als Moustache voor de hand te liggen maar desgevraagd stelde Copilot een simpele regex voor die inderdaad vooralsnog voldoet. Omdat deze renderfunctie het niet kan herkennen als er een functie wordt opgegeven in plaats van een simpele variabele worden de functieresultaten in expliciet in een tussenvariabele geplaatst zodat bij het renderen alleen variabelen hoeven te worden vervangen en geen functies geëvalueerd.
Zie: src/templating.js op Github
7. Voorinstellingen
Ik heb de JSON objecten van de patronen uitgebreid met een property ‘presets’, een array waarin met groepen voorinstellingen van de parameters. Het laat zien dat kleine veranderingen in de parameters tot ingrijpend ander aanzien van het patroon kan leiden. SVG’s die deze presets hebben krijgen een extra select-box in de Inspector Controls.
Zie: src/edit.js
Ter onderscheiding gaf ik de groepen voorinstellingen een naam. Meestal net zo vergezocht als Asanoha.
8. SVG in een block plaatsen
Wat moet er na het renderen met de svg gebeuren? SVG’s kunnen op verschillende manieren in een webpagina worden opgenomen. In principe zou de svg als bestand kunnen worden opgeslagen ( in bijvoorbeeld wp-uploads/ ) en dat bestand kan dan als achtergrond-afbeelding worden geselecteerd. Dit is evenwel niet zonder problemen want WordPress staat zonder aanpassing de upload van Svg’s niet toe.
Maar een SVG kan ook in de lopende html worden opgenomen en zelfs als achtergrond-afbeelding door een inline css styleregel als hieronder. Dit scheelt overigens ook een extra request aan de server.
background-image: url(data:image/svg+xm, 'urlencoded svg data').
Door de svg om te zetten naar een inline-styleregel kan deze in de edit- en in de save-functie aan de blockProps van het Gutenberg block worden toegevoegd.
// get the resulting svg by rendering the template and parameters
const svgResult = renderTemplate( mytemplate, myview );
// URL encode the svg
const svgDataUri = `data:image/svg+xml,${ encodeURIComponent(
svgResult
) }`;
// Add the encoded svg as an inline css background rule
blockProps = useBlockProps( {
style: { backgroundImage: `url("${ svgDataUri }")` },
} );
Het aanpassen van parameters zal hierdoor onmiddellijk resulteren in een aangepaste CSS achtergrond stijl zodat de Block Editor gelijk de achtergrond aanpast. Zoals de bedoeling was.
Zie: src/edit.js in Github
Zie src/save.js in Github
Patronen en voorinstellingen
Asanoha
Dark Night
Black River
Star Blazer
Soup
Beach
Red
Blue
Gump
Free
Crates
Metalic
Anatomy
Fragile
Ant
Diamond
Cardinal
Leaves
Polka
Candy
Rings
Elegant
Horrible 70
Awefull 80
Store
Seigaiha
Pink
Pink Gradiënt
Lime
Classic 2