COMMUNITY

Generating SVGs in vanilla Haxe

haxe-js

(Louis Tovar) #1

Hi, I am using haxe to create SVGs in the JS target, and wanted to make sure I am not missing out on a better way to do this. Essentially I have this helper function that uses document.createElementNS of the type of SVG Element I am looking to create:

//https://stackoverflow.com/questions/20539196/creating-svg-elements-dynamically-with-javascript-inside-html
// using this to be able to create svg elements with code
static function createSVGElement(n):SVGElement
{
    return cast(document.createElementNS("http://www.w3.org/2000/svg", n));
}

and using that method like this:

var svg:SVGElement = createSVGElement("svg");
svg.width.baseVal.valueAsString = "100px";
svg.height.baseVal.valueAsString = "100px";

var line:LineElement = cast(createSVGElement("line"));
line.x1.baseVal.valueAsString = "20%";
line.x2.baseVal.valueAsString = "20%";

line.y1.baseVal.valueAsString = "10%";
line.y2.baseVal.valueAsString = "35%";

line.classList.add("test-line-2");

svg.appendChild(line);


// some place doing an HTMLELEMENT.appendChild(svg);

This is working without issues, but making sure there isn’t a better way, specifically the “cast(createSVGElement(“line”))” bit


(Valentin Lemière) #2

The cast is necessary to go from a SVGElement to a LineElement.

What you could do to hide it, and avoid mistakes is to create more functions:

class SVG {
  static function create (n):SVGElement {
    return cast document.createElementNS("http://www.w3.org/2000/svg", n);
  }
  public static function create():SVGElement {
    return create("svg");
  }
  public static function createLine():LineElement {
    return cast create("line");
  }
}

and do SVG.create() and SVG.createLine().


(Allan Dowdeswell) #3

This back-end for OpenFL came out a few years ago; not sure if it’s useful. https://github.com/ngrebenshikov/openfl-snapsvg


(tokiop) #4

Franco Ponticelli’s doom has a nice way to build svgs.

For each node, the first Map contain the attributes and the second one contain the children. Your example would translate like :

var svg = svg([
  "width" => "100",
  "height" => "100",
  "viewBox" => "0 0 100 100"
], [
  line([
    "x1" => '20%',
    "x2" => '20%',
    "y1" => '10%',
    "y2" => '35%',
    "class" => 'test-line-2'
  ])
]);

The whole virtual dom might be overkill depending on your use, but the svg building can be an inspiration for a succinct creation API.