it really depends on where your circles come from... assuming all have a width and height of "300px" you can simply wrap your SVGs into another SVG that gets the position and size assigned in the loop. Then just add your SVGs with unsafeHTML (that is assuming you trust the source of your SVG strings)
import { LitElement, svg } from 'https://unpkg.com/lit-element?module'
import { unsafeHTML } from 'https://unpkg.com/lit-html/directives/unsafe-html.js?module'
const circles = {
big: `<svg viewBox="0 0 100 100" width="300px" height="300px">
<circle cx="50" cy="50" r="50"/>
</svg>`,
small: `<svg viewBox="0 0 200 200" width="300px" height="300px">
<circle cx="100" cy="100" r="60"/>
</svg>`
}
class MyExample extends LitElement {
doSomething(evt){
const index = evt.target.getAttribute("data-index")
// do something with circle i
}
render () {
return svg`
<div class="ingredients">
<svg height="50vh" width="100%" viewBox="0 0 100 100">
${Object.values(circles).map((circle, i) => {
return svg`<svg @click="${this.doSomething}" data-index="${i}" viewBox="0 0 300 300" x=${i * 20} y=${i * 20} height="30" width="30">
${unsafeHTML(circle)}
</svg>`
})}
</svg>
</div>
`
}
}
window.customElements.define('my-example', MyExample)
another way to do this is to use a DOMParser to parse your strings to a DOM, manipulate that DOM and then turn the result back to a string to render it in the render function (that is if your SVGs do not have the same width and heigh set, and it is not possible to remove the width and height Attributes):
import { LitElement, svg } from 'https://unpkg.com/lit-element?module'
import { unsafeHTML } from 'https://unpkg.com/lit-html/directives/unsafe-html.js?module'
const circles = {
big: `<svg viewBox="0 0 100 100" width="300px" height="300px">
<circle cx="50" cy="50" r="50"/>
</svg>`,
small: `<svg viewBox="0 0 200 200" width="300px" height="300px">
<circle cx="100" cy="100" r="60"/>
</svg>`
}
function setPosition (node, x, y, width, height) {
node.setAttribute('x', x)
node.setAttribute('y', y)
node.setAttribute('width', width)
node.setAttribute('height', height)
}
class MyExample extends LitElement {
render () {
const parser = new DOMParser()
return svg`
<div class="ingredients">
<svg height="50vh" width="100%" viewBox="0 0 100 100">
${Object.values(circles).map((circle, i) => {
const doc = parser.parseFromString(circle, 'image/svg+xml')
setPosition(doc.documentElement, i * 20, i * 20, 30, 30)
return unsafeHTML(doc.documentElement.outerHTML)
})}
</svg>
</div>
`
}
}
window.customElements.define('my-example', MyExample)
it really depends on where the data is coming from and what steps you can do to prepare the data... the most elegant solution would be to turn your SVG strings into template-string-returning functions. then the render function becomes really simple:
import { LitElement, svg } from 'https://unpkg.com/lit-element?module'
const circles = {
big: (x, y, w, h) => svg`<svg viewBox="0 0 100 100" x="${x}" y="${y}"" width="${w}" height="${h}">
<circle cx="50" cy="50" r="50"/>
</svg>`,
small: (x, y, w, h) => svg`<svg viewBox="0 0 200 200" x="${x}" y="${y}"" width="${w}" height="${h}">
<circle cx="100" cy="100" r="60"/>
</svg>`
}
class MyExample extends LitElement {
render () {
const parser = new DOMParser()
return svg`
<div class="ingredients">
<svg height="50vh" width="100%" viewBox="0 0 100 100">
${Object.values(circles).map((circle, i) => circle(i * 20, i * 20, 30, 30))}
</svg>
</div>
`
}
}
window.customElements.define('my-example', MyExample)
following the logic (of creating a new svg element and appending the circle from your svg strings) you use in your example will only work with the all new unsafeSVG() directive which is new in the unfinished lit-html version 1.2.0... i'm happening to host a build of that so you can try this as well:
import { LitElement, svg } from 'https://cdn.klimapartner.net/modules/lit-element/lit-element.js'
import { unsafeSVG } from 'https://cdn.klimapartner.net/modules/lit-html/directives/unsafe-svg.js'
const circles = {
big: `<svg viewBox="0 0 100 100" width="300px" height="300px">
<circle cx="50" cy="50" r="50"/>
</svg>`,
small: `<svg viewBox="0 0 200 200" width="300px" height="300px">
<circle xmlns="http://www.w3.org/2000/svg" cx="100" cy="100" r="60"/>
</svg>`
}
class MyExample extends LitElement {
render () {
const parser = new DOMParser()
return svg`
<div class="ingredients">
<svg height="50vh" width="100%" viewBox="0 0 100 100">
${Object.values(circles).map((circle, i) => {
const doc = parser.parseFromString(circle, 'image/svg+xml')
return svg`<svg viewBox="${doc.documentElement.getAttribute('viewBox')}" x=${i * 20} y=${i * 20} height="30" width="30">
${unsafeSVG(doc.documentElement.innerHTML)}
</svg>`
})}
</svg>
</div>
`
}
}
window.customElements.define('my-example', MyExample)