Skip to content

SVG and javascript

jackdarker edited this page Aug 14, 2021 · 6 revisions

My plan was to dynamical load vector-graphics and combine them to an image just like you can stack multiple images in css-background.
With the svg-<use> command it should be possible to combine the separatly loaded svg into one scene.

But I run into several problems here:

  • svg can be loaded via <img> but then you cannot access each component of svg for re-styling
  • you can either inline-embed an SVG in html or use <object> to load dynamical from a path
  • first one is ugly to edit (copy paste from svg-file)
  • I CANNOT access contentDocument (opposed to the many examples out there) from the loaded svg inside <object> because of cross-origin-blocking for local files !
  • both are creating a visible image; but I just want to get the svg loaded to be able to <use> them

So my current workaround is like this:

  • I use SVG.js to modify SVG-DOM on the fly
  • create a js-function that builds a svg-html-string for a picture (copy paste svg-code from svg-file into function; remove all line breaks)
  • those functions are called in the passage-script to add the svg-html to the <symbols>-container of the scene-svg
  • the scene can now <use> those svg-html because it exists in the html-document

Example:
//sample svg-html-generator
window.gm.images.wolf2 = function() {
return('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="wolf2">.....</svg>'); //notice that id="wolf2" is already set in the string
};
window.gm.printSceneGraphic=function() {
var width=600,height=300;
var draw = SVG().addTo('#canvas').size(width, height); //initilize SVG, pointing to scene-canvas (just a <div>)
var background = draw.rect(width, height).attr({ fill: '#f06'}); //draw a simple colored background rect
var image = draw.symbols().image('assets/battlers/slug1.svg'); //this will load the svg as image that cannot be styled!
image.node.id='slug1'; //need to add a id for <use>
var node = SVG(window.gm.images.wolf2()); //convert the SVG-string into a node
if(node) node.addTo(draw.symbols()); // and add it to symbols
draw.use('wolf2').move(-20, 20); //now we can use them refering to their id
draw.use('slug1').move(20, 20);
draw.use('wolf2').move(100, 20);
};

If you change the style of a symbol (or a use-reference), this will affect all instances of the symbol (other then the move-operation ?!). If you just want to restyle a single node, you can add the node directly to draw and change its style:
var node2 = SVG(window.gm.images.wolf2());//node2 is a SVG-document that contains SVG-elements
if(node2) node2.addTo(draw);//added to scene - not symbols !
node2.node.getElementById('wolfbody').style.fill= '#f03';//wolfbody is the id of the svg-element, f.e. a path

If you dont have the node anymore, you can find it:
node3.node.id='wolf3a'; //make sure to give the node a unique id
... later...
SVG.find('#wolf3a #wolfbody')[0].node.style.fill= '#f03';//this will find the subelement of id wolfbody inside node of id wolf3a

Todo: how to load a svg-file from disk and append its content to <devs>-container of scene-svg? This is not possible because of cross-origin-blocking?

Clone this wiki locally