{"id":676,"date":"2020-09-14T19:37:26","date_gmt":"2020-09-14T19:37:26","guid":{"rendered":"https:\/\/potatodie.nl\/diffuse-write-ups\/?p=676"},"modified":"2020-10-05T12:11:36","modified_gmt":"2020-10-05T12:11:36","slug":"svg-sprites-transforms","status":"publish","type":"post","link":"https:\/\/potatodie.nl\/diffuse-write-ups\/svg-sprites-transforms\/","title":{"rendered":"SVG sprites transforms"},"content":{"rendered":"\n<p>Since working with SVG transforms can get difficult, especially setting transform origin, I often use <a href=\"https:\/\/greensock.com\/\">GreenSock <\/a>to avoid transform trouble.<\/p>\n\n\n\n<p>To make a series of icon elements rotate or scale around its center, for example, you could code<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-js\">\n      JS    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1349708719\" \n    id=\"codemirror-1349708719\"\n  >gsap.set(icons, {\n    transformOrigin: &quot;50% 50%&quot;,\n});\n\ngsap.to(icons, {scale: 2, rotation: 90});<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1349708719'), {\n      mode: 'javascript',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p>Here&#8217;s a more elaborate example:<\/p>\n\n\n\n<p class=\"codepen\" data-height=\"265\" data-theme-id=\"dark\" data-default-tab=\"js,result\" data-user=\"potatoDie\" data-slug-hash=\"MWyXOGV\" style=\"height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Set SVG sprites transform origin with GreenSock\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/potatoDie\/pen\/MWyXOGV\">\n  Set SVG sprites transform origin with GreenSock<\/a> by potatoDie (<a href=\"https:\/\/codepen.io\/potatoDie\">@potatoDie<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<p>Still there are occasions when the troubles I thought were conquered nightmarishly reappear. For instance if we use sprites in an external file and Vue.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Are the sprites loaded yet?<\/h2>\n\n\n\n<p>Suppose we want to use a sheet of sprites for the graphics in a game. This means we have a separate SVG file with a bunch of graphics, probably as symbols. Here&#8217;s a simple example with two chess pieces:<\/p>\n\n\n<div class=\"wp-block-advanced-gutenberg-blocks-code\">\n  <header class=\"wp-block-advanced-gutenberg-blocks-code__header\">\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__lang is-lang-html\">\n      HTML    <\/div>\n    <div class=\"wp-block-advanced-gutenberg-blocks-code__file\">\n          <\/div>\n  <\/header>\n  <textarea \n    class=\"wp-block-advanced-gutenberg-blocks-code__source\" \n    name=\"codemirror-1939658564\" \n    id=\"codemirror-1939658564\"\n  >&lt;svg\n   xmlns=&quot;http:\/\/www.w3.org\/2000\/svg&quot;\n   version=&quot;1.1&quot;\n   viewBox=&quot;0 0 200 200&quot;\n   height=&quot;200&quot;\n   width=&quot;200&quot;&gt;\n  &lt;defs\n     id=&quot;defs4254&quot;&gt;\n    &lt;symbol\n       id=&quot;rook&quot;\n       viewBox=&quot;0 100 100 100&quot;&gt;\n      &lt;path\n         d=&quot;m 10,110 v 20 h 10 v 40 H 10 v 20 H 90 V 170 H 80 V 130 H 90 V 110 H 70 v 10 H 60 V 110 H 40 v 10 H 30 v -10 z&quot; \/&gt;\n    &lt;\/symbol&gt;\n    &lt;symbol\n       id=&quot;bishop&quot;\n       viewBox=&quot;100 0 100 100&quot;&gt;\n      &lt;path\n         d=&quot;M 150 10 C 130 20 100 40 130 70 L 110 70 L 110 90 L 190 90 L 190 70 L 170 70 C 200 40 170 20 150 10 z M 145 30 L 155 30 L 155 50 L 145 50 L 145 30 z &quot; \/&gt;\n    &lt;\/symbol&gt;\n  &lt;\/defs&gt;\n&lt;\/svg&gt;<\/textarea>\n  <script>\n    CodeMirror.fromTextArea( document.getElementById('codemirror-1939658564'), {\n      mode: 'xml',\n      readOnly: true,\n      theme: 'hopscotch', \n      lineNumbers: true,\n      firstLineNumber: 1,\n      matchBrackets: true,\n      indentUnit: 4,\n      tabSize: 4,\n      lineWrapping: true,\n    } ); \n  <\/script>\n<\/div>\n\n\n\n<p>In a Vue component you could import the sprite sheet, pick the symbol you like, refer to it in a <code>use<\/code> element and let GreenSock handle the transform for you.<\/p>\n\n\n\n<p>Unfortunately this brings back the transform origin quirk. During Vue&#8217;s mounted hook the sprite sheet may not be loaded yet and setting the tranform origin doesn&#8217;t work, even though the width and height of the <code>use<\/code> tag may be set.<\/p>\n\n\n\n<p>To solve this either set the transform origin in SVG units. Or wait till the sprite file is loaded and then set <code>transformOrigin<\/code> to <code>\"50% 50%\"<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Safari problems<\/h2>\n\n\n\n<p>It appears Safari doesn&#8217;t take the <code>x<\/code> and <code>y<\/code> value of the use element in account, when setting the <code>transformOrigin<\/code>. In the above Codepen you see in Safari that the rooks do not animate on their spot. I fixed it for the bishops, wrapping the use elements in a group with a transform, so the <code>x<\/code> and <code>y<\/code> coordinate of the <code>use<\/code> are zero.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Investigation if working with SVG sprites is practical. Especially in combination with transforms.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[38,15,12,35],"class_list":["post-676","post","type-post","status-publish","format-standard","hentry","category-web-development","tag-greensock","tag-svg","tag-transform","tag-vue-js"],"acf":[],"_links":{"self":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/comments?post=676"}],"version-history":[{"count":7,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/676\/revisions"}],"predecessor-version":[{"id":812,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/posts\/676\/revisions\/812"}],"wp:attachment":[{"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/media?parent=676"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/categories?post=676"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/potatodie.nl\/diffuse-write-ups\/wp-json\/wp\/v2\/tags?post=676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}