Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create SVG image by merging other SVG files

I like to create a svg file based on two arrays the first array hold the paths to svg files that should be combined in one svg resource that is described by another array

Array of paths to pattern graphics

These patterns are available as vector files. Each pattern has a size of 200x200px
See content of the files below.

$pathesToPatternsArray = array("0"=>"circle.svg", "1"=>"square.svg");

Array that describe the position of the patterns on an image

$positionOnTheImageArray = array(
0=>array(0,0,0,0),
1=>array(0,0,0,0),
2=>array(1,1,1,1),
3=>array(1,1,1,1),
4=>array(1,0,1,0);

The Result:

So we got an image with 5 rows. The first two rows contain only circles. The next two rows contain only squares. The last row contains "square,circle,square,circle"

Pseudocode

This is the way I think it will work but unfortunately I don't know how to handle the SVG merging. I hope you can help me with this. I think it will work maybe with GD, Imagick or simple text file handling but I couldn't find a solution yet.

<?php

$svgOutputfile = createSVGFileRessource();

foreach($positionOnTheImageArray AS $row => $cellArray)
{
  $cell = 0;
  foreach($cellArray AS $selectedPattern)
  {
     $pattern = loadPattern($pathesToPatternsArray[$selectedPattern]);
     $svgOutputfile->write($row,$cell,$pattern);
     $cell++;
  }

$svgOutputfile->save();

Content of triangle.svg

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<circle fill="#000000" stroke="#000000" stroke-miterlimit="10" cx="100" cy="100" r="100"/>
</svg>

Content of square.svg

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<rect y="0" fill="#000000" stroke="#000000" stroke-miterlimit="10" width="200" height="200"/>
</svg>

Finaly

I'm really looking forward to an answer that helps me to find a solution.

like image 520
funktioneer Avatar asked Apr 19 '14 19:04

funktioneer


1 Answers

I am not sure if you are asking how to make the SVG work, or how to do XML manipulations in PHP. I am going to assume the former.

Approach 1 - the straightforward way

You are allowed to nest SVG elements. SO an arrangement like the following is legal:

<svg>
  <svg></svg>
  <svg></svg>
  <svg></svg>
  ..etc..
</svg>

So what you can do is write out a suitable top level <svg> element:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 width="800px" height="1000px" viewBox="0 0 800 1000">

Then append all your child SVGs in row and column order. However, you'll need to do two things to each of them as you copy them over.

  1. Strip the XML preamble (<?xml> and <!DOCTYPE>).
  2. Add x and y attributes to re-position them as per their array positions. Ie. x200 and y200

Demo here

Note that there are some potential stumbling blocks. For example, you may have check for and avoid duplicate id attributes. They are supposed to be unique. For these simple SVGs it won't matter, but if you end up using more complicated SVGs for your cells, it may be an issue.

Approach 2 - with Use elements

In this method, you only include each child SVG once, and then reference them with a <use> element for each cell.

<svg>
   <defs>
      <svg id="circle">...</svg>
      <svg id="square">...</svg>
   </defs>

   <use xlink:href="circle"/>
   <use xlink:href="square"/>
   ..etc..
</svg>

Which will result in a much smaller file and will be a lot simpler to understand and build with code.

Demo here

like image 150
Paul LeBeau Avatar answered Oct 01 '22 15:10

Paul LeBeau