8

When I embed an SVG symbol in QGIS 3.x, the symbol is stored in the layer definition. If I have another layer and like to use the symbol again, I have to embed it a second time.

How can I embed an SVG symbol globally and use it in multiple layers?

christoph
  • 5,605
  • 1
  • 20
  • 34

3 Answers3

11

Found the answer to my problem: We can store the base64 encoded SVG string in a project variable and link to this variable (i.e. 'mySymbol').

base64:PHN2ZyBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1NzkuOTk3IDU3OS45OTciIGhlaWdodD0iNTc5Ljk5NyIgdmlld0JveD0iMCAwIDU3OS45OTcgNTc5Ljk5NyIgd2lkdGg9IjU3OS45OTciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Im0yODkuOTk3IDMzLjMxbC0yMjQuNjEgNTEzLjc2NSAyMjAuNDk5LTE0My45NDYgMjI4LjYzMiAxNDMuNzM2eiIgZmlsbD0icGFyYW0oZmlsbCkiIGZpbGwtb3BhY2l0eT0icGFyYW0oZmlsbC1vcGFjaXR5KSIgc3Ryb2tlPSJwYXJhbShvdXRsaW5lKSIgc3Ryb2tlLW9wYWNpdHk9InBhcmFtKG91dGxpbmUtb3BhY2l0eSkiIHN0cm9rZS13aWR0aD0icGFyYW0ob3V0bGluZS13aWR0aCkiLz4KPC9zdmc+Cg==

enter image description here

christoph
  • 5,605
  • 1
  • 20
  • 34
  • 2
    Great idea -- a very elegant solution! – ndawson Sep 16 '20 at 22:36
  • 3
    Unfortunately, this only works with simple symbols, because project variables are limited to a length < 6000 characters. But fortunately, we can use Expression functions as well to retrieve complex symbols (i.e. base64 encoded SVGs with base64 encoded images embedded) from somewhere else. – christoph Sep 17 '20 at 16:25
  • 4
    A better solution: storing symbol names and base64 strings in a Geopackage table "svg" and using expression functions to select the symbols -- [ attribute( get_feature( 'svg','name','mySymbol'),'symbol') ] – christoph Sep 17 '20 at 18:01
  • In this case you will have to copy/paste the table "svg" into another GeoPackage every time before sending this GeoPackage to another person, if you need to share this geospatial data, right? – KVO Nov 07 '23 at 16:24
  • @KVO that‘s correct. – christoph Nov 07 '23 at 16:31
5

While playing around with Data URIs, I managed to store SVG images inline without base64 encoding. Only have to put 'data:image/svg+xml;utf8,' in front. Depending on the SVG content, the inline SVG data strings are much smaller without encoding.

'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" height="100px" width="100px"><path fill="param(fill) #000000" d="M50,2.5c-19.2,0-34.8,15-34.8,33.4C15.2,61.3,50,97.5,50,97.5s34.8-36.2,34.8-61.6  C84.8,17.5,69.2,2.5,50,2.5z M50,48.2c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9c7.1,0,12.9,5.8,12.9,12.9  C62.9,42.4,57.1,48.2,50,48.2z"/></svg>'
christoph
  • 5,605
  • 1
  • 20
  • 34
1

Following @christoph's advice, the data:image format is working for me, but with the svg as xml-encoded, like this:

<prop v="data:image/svg+xml;utf8,&lt;svg enable-background=&quot;new 0 0 580 580&quot; height=&quot;580&quot; viewBox=&quot;0 0 580 580&quot; width=&quot;580&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path d=&quot;m504.911 519.52l.713-.006-10.927-19.284-190.172-360.682 35.603-67.259-23.227-12.295-27.214 51.412-28.368-53.804-23.246 12.257 36.007 68.292c-15.495 32.074-121.491 230.255-192.826 362.816l-10.441 19.403 94.237-.156 23.41.181.115-.22 202.599-.336.291.556 91.769-.708 21.747-.036zm-214.949-233.661c21.655 72.987 67.317 167.251 87.688 207.723l-175.523.29c20.298-40.308 66.127-134.848 87.835-208.013z&quot; fill=&quot;param(fill)&quot; fill-opacity=&quot;param(fill-opacity)&quot; stroke=&quot;param(outline)&quot; stroke-opacity=&quot;param(outline-opacity)&quot; stroke-width=&quot;param(outline-width)&quot;/&gt;&lt;/svg&gt;" k="name"/>
Matt
  • 16,843
  • 3
  • 21
  • 52