technodesigner

Digital design

Olivier Dewit
Template based code generation - Part 3 : SVG transformations

Template based code generation - Part 3 : SVG transformations

Series index

Next parts of this article assume that the tdCodeFactory module is installed and opérational.

In the Github repository , the source code for this example is available in the Demo/3.ShapeFactory and Demo/CsCode folders.

SVG transformations

Our third example is about how to apply transforms to rectangles.

An alternative would be to use CSS transforms, but they are not supported on SVG elements by IE.

SVG transformations are defined using the transform attribute on XML elements that support them.

If several objects use the same factors of transformation, their transform attribute becomes redundant, and the code becomes less maintainable.

The only way to make reusable definitions of transformation is to use the DTD entities.

Our generator thus produces SVG code that exploits this technique to define potentially reusable transformations:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
  <!ENTITY transformData1 'matrix(0.5, 0, 0, 0.5, 0, 0)'>
  <!ENTITY transformData2 'matrix(0.7, 0, 0, 0.7, 15, 15)'>
  <!ENTITY transformData3 'matrix(1, 0, 0, 1, 15, 30)'>
]>
<svg xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 200 150">
...
  <rect 
    class='rectStyle1' 
    x='10'
    y='10'
    width='80'
    height='40'
    rx='4'
    ry='4'
    transform='&transformData1;' />
...
</svg>

An introduction to matrix transformations is available here

Code generation of transformations

To generate this code, we first define a C# class for storing information about a transformation:

public class TransformData
{
  public string Name { get; set; }
  public double TranslateX { get; set; }
  public double TranslateY { get; set; }
  public double ScaleX { get; set; }
  public double ScaleY { get; set; }
  public TransformData()
  {
    ScaleX = 1;
    ScaleY = 1;
  }
}

The TranslateX and TranslateY properties determine the displacement of the target shape. ScaleX and ScaleY properties determine the scale factor.

The RectData class is extended by a TransformDataName property that is used to associate an instance of the TransformData class.

The script uses these classes as follows:

$code = {
  ...
  $transformDataCsCode = Import-CodeTemplate $PSScriptRoot\..\CsCode\TransformData.cs
  Add-Type -Language CSharp $transformDataCsCode
  $transformData1 = New-Object CodeFactory.TransformData -Property @{
    Name = "transformData1";
    ScaleX = 0.5;
    ScaleY = 0.5;
  }
  $transformData2 = New-Object CodeFactory.TransformData -Property @{
    Name = "transformData2";
    TranslateX = 15;
    TranslateY = 15;
    ScaleX = 0.7;
    ScaleY = 0.7;
  }
  $transformData3 = New-Object CodeFactory.TransformData -Property @{
    Name = "transformData3";
    TranslateX = 15;
    TranslateY = 30;
  }
  $script:transforms = @(
    $transformData1; 
    $transformData2;
    $transformData3 )
  $rectDataCsCode = Import-CodeTemplate $PSScriptRoot\..\CsCode\RectData.cs
  Add-Type -Language CSharp $rectDataCsCode
  $rect1 = New-Object CodeFactory.RectData -Property @{
    Name = "rect1";
    StyleDataName = $rectStyle1.Name;
    TransformDataName = $transformData1.Name;
    X = 10;
    Y = 10;
    Width = 80;
    Height = 40;
    RadiusX = 4;
    RadiusY = 4;
  }
...
}

Finally, the template uses these variables and tables to structure the SVG code appropriately:

$(i0)<?xml version="1.0"?>
$(i0)<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
$(i=)$(foreach ($transform in $transforms){"
$(i+)<!ENTITY $($transform.Name) 'matrix($($transform.ScaleX), 0, 0, $($transform.ScaleY), $($transform.TranslateX), $($transform.TranslateY))'>
$(i-)`r`n"})
$(i0)]>
$(i0)<svg xmlns="http://www.w3.org/2000/svg"
$(i+)viewBox="0 0 $($shapeboard.Width) $($shapeboard.Height)">
...
$(i-)$(foreach ($rect in $shapes){"
$(i=)<rect 
$(i+)class='$($rect.StyleDataName)' 
$(i=)x='$($rect.X)'
$(i=)y='$($rect.Y)'
$(i=)width='$($rect.Width)'
$(i=)height='$($rect.Height)'
$(i=)rx='$($rect.RadiusX)'
$(i=)ry='$($rect.RadiusY)'
$(i=)$(if ($rect.TransformDataName){'transform=''&' + $($rect.TransformDataName) + ';'''}) />
$(i-)`r`n"})
$(i0)</svg>

Result

The generated SVG file is viewable in a browser:

PowerShell : SVG code generation with transformations

Summary

Here we have applied SVG transformations and made reusable their definition. In future articles, we will discuss in particular the following topics:



Powered by the Perspective WebApp - © Olivier Dewit - Lyon, Paris, France - Legal informations