Reputation: 357
I am trying to dynamically render the content of a SVG element using svg.js library (https://svgjs.dev). Everything works fine when creating basic elements, like lines, polygons and simple textx and working with their properties.
Now, I would like to extend the drawing with more complex elements using ready-made SVGs (available in a hidden div on the page or by other means), that I need to somehow 'clone' to the main SVG element and also adjust the size and position.
The image below is an example of what I am trying to accomplish : the rectangle is created with svgjs' svg.polygon().plot(... )
, and I would like to add the trees.
What would be the simple/proper way to do this ?
Upvotes: 1
Views: 595
Reputation: 357
Once again, a good night's sleep provides the right answer, and it's a lot easier than what I expected.
Turns out all is needed is a use
, with the svg element id and, optionally, an URL to load the SVG file from, which saves one from embedding the SVG into the page :
// the definition of the object to embed
// holds the item id, and transformation data
var item = ...;
var g = svg
.group()
.use(
item.src,
resURL + '/svg/sprites.svg')
.transform({
translateX : item.x,
translateY : item.y });
For SVGs outside your domain, you probably need to load them differently.
As requested, below is a still partial, but more detailed code sample; adding the full code would make the solution hard to follow.
DISCLAIMER : I haven't got to the optimizations / refactoring yet, so yes, there's probably a lot of room to improve on both the data and the code.
The data is a JSON structure like so :
{
"items" : {
"item1" : {
"points" : [[1600,200],[2300,200],[2300,600],[1600,600],[1600,200]],
"fill" : "rgba(144, 238, 144, 0.3)",
"stroke" : "#228B22"
},
"item2" : {
"src":"sprite1"
"style":{
"opacity" : 0.3
},
"position":{
"x" : -360,
"y" : 75,
"scale" : 0.8
},
}
},
}
The processing goes like this :
var svg = SVG("#drawing-" + floor.key)
Object.keys(floor.items).forEach(function(key,index) {
var item = floor.items[key];
if (item.hasOwnProperty('points')) {
var polygon = svg
.polygon()
.stroke({
color: item.stroke })
.fill(item.fill);
polygon.plot(item.points);
}
else if (item.hasOwnProperty('src')) {
var g = svg
.group()
.use(item.src, resURL + '/svg/plan-sprites.svg')
.transform({
translateX : item.position.x,
translateY : item.position.y,
scale : item.position.scale || 1.})
.css(item.style || { });
}
});
When done, the page looks like this (simplified) :
<svg id="drawing-curte" class="hwb-drawing"
<g id="viewport">
<polygon points="1600,200 2300,200 2300,600 1600,600 1600,200" stroke="#228b22" fill="#90ee90"></polygon>
<g><use xlink:href="/resources/svg/plan-sprites.svg#sprite1" transform="matrix(1,0,0,1,1550,150)"></use></g>
</g>
</svg>
Upvotes: 2