Animate shape in typography mask SVG - svg

For my new website, I want to mask a morphing shape inside a typography like clip path property. I have done the morphing but not the mask, any idea ?
I put 2 photos of my example and a jsFiddle.
My Example :
jsFiddle exemple : http://jsfiddle.net/aw8zvsbn/32/
s = Snap(1000, 500);
s.attr('fill', 'red');
s.attr({ viewBox: "80 230 340 100" });
var path = s.path("m238 324c-19.4 0.618-33.4-27.3-47.6-37-8.27-5.66-35.8-21.4-28.5-35 2.51-4.67 18.8-4.3 22.4-5.5 11.4-3.83 15.8-10.8 25.8-16.6 29.7-17.2 32.2 14.8 58.1 11.5 8.36-1.06 13.3-11.8 21.4-14.3 10.6-3.22 20.8 1.61 31 5.74 18.4 7.48 25.4 13.8 13.5 36.2-12.2 22.9-27.6 9.32-43.3 23.5-7.57 6.78-7.33 16.8-16 23-9 7-26 9-37 9-12 0 15 0 0 0z");
path.animate({ d: "m187 302c-13.3-0.667-12.9 9.71-27.5-0.5-9.9-6.91-6.5-13.6-3-28.2 3-15-12-37 3-44 11.1-5.07 35 16.9 54 20s26.4-20 45.2-17.2 11.1 15.4 34.3 16.8c20.6 1.2 60.8-0.555 55.7 22.7-6.36 29-44 23-61.7 33.5-10.3 6.1-25-13.4-33.2-6-10.3 9.38-21.3 14.2-33.3 15.2s-21-12-34-13z" }, 6000, mina.linear);
Any help would be precious.
Sorry for my english, I'm French

You just mask the animated blob with some <text>.
Plain SVG example below. I'll let you translate it to a Snap script.
<svg viewBox="80 230 340 100">
<defs>
<!-- some text we will use for masking the red blob,
and also for the green text in the background.
We define it here once so we don't have to repeat it twice. -->
<g id="mytext" font-size="50" font-family="sans-serif" font-weight="bold">
<text x="100" y="270">CLOTHING</text>
<text x="150" y="310">BRAND</text>
</g>
<!-- Define the mask that we will use to show only part of the red blob -->
<mask id="textmask">
<use xlink:href="#mytext" fill="white"/>
</mask>
</defs>
<!-- Display an instance of the text in green -->
<use xlink:href="#mytext" fill="limegreen"/>
<!-- The red blob masked with our text mask -->
<path d="M187,302C173.7,301.333,174.1,311.71,159.5,301.5C149.6,294.59,153,287.9,156.5,273.3C159.5,258.3,144.5,236.3,159.5,229.3C170.6,224.23000000000002,194.5,246.20000000000002,213.5,249.3C232.5,252.4,239.9,229.3,258.7,232.10000000000002C277.5,234.90000000000003,269.8,247.50000000000003,293,248.90000000000003C313.6,250.10000000000002,353.8,248.34500000000003,348.7,271.6C342.34,300.6,304.7,294.6,287,305.1C276.7,311.20000000000005,262,291.70000000000005,253.8,299.1C243.5,308.48,232.5,313.3,220.5,314.3C208.5,315.3,199.5,302.3,186.5,301.3C186.5,301.3,187,302,187,302C187,302,187,302,187,302" fill="#ff0000" mask="url(#textmask)"></path>
</svg>

Related

Safari does not update textPath when path data is changed dynamically

I have a path which I'm referencing from a textPath element in SVG, I'm updating the path data dynamically. This works fine in Chrome and Firefox, but Safari (v16.1) is not updating the textPath to reflect the updated path data.
Here is the stripped down use case:
const path = document.querySelector("path");
setInterval(function(){
path.setAttribute("d", `M ${Math.random()*20} ${Math.random()*400} C 11 195 385 105 789 227`)
}, 100);
<svg width="800" height="400" viewBox="0 0 800 400">
<text>
<textPath text-anchor="middle" startOffset="50%" href="#tp-path" font-size="51" font-family="sans-serif">Lorem Ipsum</textPath>
</text>
<path d="M 22 400 C 11 195 385 105 789 227" fill="none" stroke="#ccc" id="tp-path"></path>
</svg>
Seems like a bug to me, any help working around it would be appreciated.
I found one workaround: if I add the href attribute dynamically it will work in Safari:
const path = document.querySelector("path");
const textPath = document.querySelector("textPath");
textPath.setAttribute("href", "#tp-path");
setInterval(function(){
path.setAttribute("d", `M ${Math.random()*20} ${Math.random()*400} C 11 195 385 105 789 227`)
}, 100);
<svg width="800" height="400" viewBox="0 0 800 400">
<text>
<textPath text-anchor="middle" startOffset="50%" font-size="51" font-family="sans-serif">Lorem Ipsum</textPath>
</text>
<path d="M 22 400 C 11 195 385 105 789 227" fill="none" stroke="#ccc" id="tp-path"></path>
</svg>

Creating custom icon for FontAwesome 5

I'm trying to create my custom icon for FontAwesome using this tool: https://editor.method.ac/
It came with code:
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg">
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
<g>
<title>background</title>
<rect fill="#fff" id="canvas_background" height="514" width="514" y="-1" x="-1"/>
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
</g>
</g>
<g>
<title>Layer 1</title>
<path id="svg_3" d="m367.967458,193.5l-23.50001,13.50001c0.00001,0.49999 -65.99999,-58.00001 -118,-53.00001c-52,5 -55.5,39.500009 -49,71.00001c6.5,31.5 14,63 64,111.5c50.00001,48.50001 97.50001,63.00001 119.50001,62.50001c22,-0.5 22.5,-1.5 29,-4c6.5,-2.5 8,-4.5 8,-4.5c0,0 59.49997,60.49998 61.99999,63.49999c2.50002,3.00001 -14.99998,42.50001 -80.49999,44.50001c-65.5,2 -162.50001,-44 -231.50001,-113c-69.00001,-69.00001 -100.50001,-130.00001 -103.50001,-213.00002c-3,-83.000009 62.500008,-97 90.500009,-100c28.000001,-3 85.000011,8.5 132.500011,39c47.5,30.5 68.99999,43.00001 100.5,82z" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="#fff"/>
<path id="svg_5" d="m258.451949,258.000015l47.75001,-31.000008c0.249993,0.000007 81.249998,71.000011 105.75,36.500009c24.500001,-34.500002 -27.000002,-96.000006 -55.000004,-127.500008c-28.000001,-31.500002 -90.000005,-55.500003 -90.249997,-55.500005c0.249992,0.000002 -57.750012,-66.500002 -58.500002,-68.000003c0.000006,0.499993 46.500009,12.499994 106.500012,54.999997c60.000004,42.500002 129.000008,139.500008 141.000009,170.00001c12,30.500002 19.000001,75.500004 -3.5,94.000005c-22.500002,18.500001 -64.000004,8.000001 -90.500006,-2.5c-26.500001,-10.5 -64.500004,-41.000002 -71.500004,-45.000002c-7.000001,-4.000001 -31.500002,-25.500002 -31.750018,-25.999995z" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="#fff"/>
</g>
</svg>
It looks good in browser.
So I prepared code for FontAwesome using this guide: https://github.com/FortAwesome/Font-Awesome/wiki/Customize-Font-Awesome
const faMyCustomIcon = {
prefix: 'fac',
iconName: 'my-custom-icon',
icon: [512, 512, [], 'e001', 'm367.967458,193.5l-23.50001,13.50001c0.00001,0.49999 -65.99999,-58.00001 -118,-53.00001c-52,5 -55.5,39.500009 -49,71.00001c6.5,31.5 14,63 64,111.5c50.00001,48.50001 97.50001,63.00001 119.50001,62.50001c22,-0.5 22.5,-1.5 29,-4c6.5,-2.5 8,-4.5 8,-4.5c0,0 59.49997,60.49998 61.99999,63.49999c2.50002,3.00001 -14.99998,42.50001 -80.49999,44.50001c-65.5,2 -162.50001,-44 -231.50001,-113c-69.00001,-69.00001 -100.50001,-130.00001 -103.50001,-213.00002c-3,-83.000009 62.500008,-97 90.500009,-100c28.000001,-3 85.000011,8.5 132.500011,39c47.5,30.5 68.99999,43.00001 100.5,82zm258.451949,258.000015l47.75001,-31.000008c0.249993,0.000007 81.249998,71.000011 105.75,36.500009c24.500001,-34.500002 -27.000002,-96.000006 -55.000004,-127.500008c-28.000001,-31.500002 -90.000005,-55.500003 -90.249997,-55.500005c0.249992,0.000002 -57.750012,-66.500002 -58.500002,-68.000003c0.000006,0.499993 46.500009,12.499994 106.500012,54.999997c60.000004,42.500002 129.000008,139.500008 141.000009,170.00001c12,30.500002 19.000001,75.500004 -3.5,94.000005c-22.500002,18.500001 -64.000004,8.000001 -90.500006,-2.5c-26.500001,-10.5 -64.500004,-41.000002 -71.500004,-45.000002c-7.000001,-4.000001 -31.500002,-25.500002 -31.750018,-25.999995z']
};
Problem is that result is this:
And should be this: (or near)
What I'm doing wrong?
This is not the answer you are expecting. I would have putted it as a comment but I need to add some code.
This is how a FontAwesome icon is looking like in SVG:
no width attribute,
no height attribute,
a viewBox attribute
inside nothing else but one path with a fill="currentColor" attribute
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="address-book" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-address-book fa-w-14 fa-7x"><path fill="currentColor" d="M436 160c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20V48c0-26.5-21.5-48-48-48H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h320c26.5 0 48-21.5 48-48v-48h20c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20v-64h20c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20v-64h20zm-228-32c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H118.4C106 384 96 375.4 96 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2z" class=""></path></svg>
Your SVG has:
a width attribute,
a height attribute,
NO viewBox attribute
inside 2 groups the second one with 2 paths.
I think you should try using only one path. In order to join the 2 paths in one path ypu can do something like this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path id="svg_3" d="m367.967458,193.5l-23.50001,13.50001c0.00001,0.49999 -65.99999,-58.00001 -118,-53.00001c-52,5 -55.5,39.500009 -49,71.00001c6.5,31.5 14,63 64,111.5c50.00001,48.50001 97.50001,63.00001 119.50001,62.50001c22,-0.5 22.5,-1.5 29,-4c6.5,-2.5 8,-4.5 8,-4.5c0,0 59.49997,60.49998 61.99999,63.49999c2.50002,3.00001 -14.99998,42.50001 -80.49999,44.50001c-65.5,2 -162.50001,-44 -231.50001,-113c-69.00001,-69.00001 -100.50001,-130.00001 -103.50001,-213.00002c-3,-83.000009 62.500008,-97 90.500009,-100c28.000001,-3 85.000011,8.5 132.500011,39c47.5,30.5 68.99999,43.00001 100.5,82z
M258.451949,258.000015l47.75001,-31.000008c0.249993,0.000007 81.249998,71.000011 105.75,36.500009c24.500001,-34.500002 -27.000002,-96.000006 -55.000004,-127.500008c-28.000001,-31.500002 -90.000005,-55.500003 -90.249997,-55.500005c0.249992,0.000002 -57.750012,-66.500002 -58.500002,-68.000003c0.000006,0.499993 46.500009,12.499994 106.500012,54.999997c60.000004,42.500002 129.000008,139.500008 141.000009,170.00001c12,30.500002 19.000001,75.500004 -3.5,94.000005c-22.500002,18.500001 -64.000004,8.000001 -90.500006,-2.5c-26.500001,-10.5 -64.500004,-41.000002 -71.500004,-45.000002c-7.000001,-4.000001 -31.500002,-25.500002 -31.750018,-25.999995z" fill="currentColor" />
</svg>
I hope it helps.

Where can I find (or make) Material Design Icon set for dense layouts (20dp, desktop)

Google Material Design guidance says:
On desktop, when the mouse and keyboard are the primary input methods, measurements may be scaled down to 20dp.
Moreover, I see that new Gmail uses 20dp-sized icons(screenshot was taken on non-high DPI display):
At the same time, I cannot find MD icons of this size anywhere. Google MD icons only offers 18dp, 24dp and bigger. Same thing in the repository. But I need exactly the size of 20dp.
I tried to use icomoon.io to change grid to 20px and tried to use icon font with the size of 20px. Both methods produce blurry icons, of course.
Where can I find them?Or, how can I up/downscale existing MD icons?
UPDATE:
This is the original icon from Gmail (20px):
https://www.gstatic.com/images/icons/material/system/1x/archive_black_20dp.png
And this is SVG, with the 24px and the desired 20px size.
On my non-high DPI screen this 20px SVG is blurry.
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24H0z' fill='none'></path>
<path d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>
<svg width='20' height='20' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
You can use the SVG attribute - shape-rendering =" crispEdges " to disable browser anti-aliasing.
https://developer.mozilla.org/ru/docs/Web/SVG/Attribute/shape-rendering
crispEdges
Indicates that the user agent shall attempt to emphasize the contrast
between clean edges of artwork over rendering speed and geometric
precision. To achieve crisp edges, the user agent might turn off
anti-aliasing for all lines and curves or possibly just for straight
lines which are close to vertical or horizontal. Also, the user agent
might adjust line positions and line widths to align edges with device
pixels.
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g" shape-rendering="crispEdges">
<path d='M0 0h24v24H0z' fill='none'></path>
<path d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>
<svg width='20' height='20' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
An .svg element can take whatever size you want.
svg{border:1px solid;}
<svg width='15' height='15' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24h-24z' fill='none'></path>
<path d='M4 10v7h3v-7h-3zm6 0v7h3v-7h-3zm-8 12h19v-3h-19v3zm14-12v7h3v-7h-3zm-4.5-9l-9.5 5v2h19v-2l-9.5-5z'></path>
</g>
</svg>
<svg width='48' height='48' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
<svg width='60' height='60' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
UPDATE
This is an answer for the OP updated question:
I've made some changes in your code and now you have a 20/20 px svg:
Your icon has a lot of white space around the image. I've removed that space.
<svg width='20' height='20' viewBox='3 3 18 18'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24H0z' fill='none'></path>
<path id="B" d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>

SVG: Mask not working as expected

I have this rather basic SVG with a vertical line going through 4 circles. The mask that I have for the vertical line has the same definition as the line itself, the only difference being the stroke color (#fff in this case) because I want to be able to see through the mask. But, for unknown reasons, the mask still acts as if the color is black, thus hiding the element. If anyone knows why it's behaving like this, please let me know.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<defs>
<mask id="education">
<path class="through" fill="none" stroke="#fff" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
</mask>
</defs>
<path class="arrow" fill="#C57773" d="M191.9 41.5l8.1-14 8.1 14"/>
<path style="mask: url(#education);" class="through" fill="none" stroke="#58595B" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
<path class="circle2" fill="#C95147" d="M200 234.7c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle1" fill="#C95147" d="M200 317.2c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle3" fill="#C95147" d="M200 152c-4.6 0-8.3 3.7-8.3 8.3 0 4.6 3.7 8.3 8.3 8.3 4.6 0 8.3-3.7 8.3-8.3 0-4.5-3.7-8.3-8.3-8.3z"/>
<path class="circle4" fill="#C95147" d="M200 67.1c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
</svg>
P.S. Just started tinkering around with SVG, but this (the element dissapearing) happens no matter what shape I define in the mask or what color I give that shape.
SVG is not like CSS, it doesn't use the stroke-width when calculating dimensions for masks and filters, so you can't mask a shape like a horizontal or vertical line (zero-height/zero-width bounding box) using default mask parameters. Just add "maskUnits="userSpaceOnUse" to your mask element to fix.
<mask id="education" maskUnits="userSpaceOnUse">

How can I make my embedded svg image stetch to fill a container?

I have an embedded svg that is will only stretch to about 2/3 of it's container size. I would like to get it to fill the entire container.
Here's how it currently looks:
I have a plunker here showing the embedded svg: http://plnkr.co/edit/5PbBmhV6aBiAtanXTVgM
The simplified svg structure is like this:
<svg id="approach_shot" viewBox="0 0 360 360" preserveAspectRatio="xMinYMin meet" class="content">
<rect fill="#FFFFFF" stroke="#000000" stroke-width="0.5" width="360" height="360"></rect>
<g id="green">
<defs>
<circle id="ball" r="6" stroke="#000000" fill="#FFFFFF" stroke-width="0.5"></circle>
</defs>
<g>
<path fill="#005C1F" stroke="#005C1F" stroke-width="0.75" stroke-miterlimit="10" d="M42.09 171.26c-10.48-25.3-9.77-52.43-0.17-75.92l-18.48-7.65c-11.56 28.22-12.42 60.83 0.17 91.23 0.08 0.2 0.17 0.4 0.25 0.6l18.48-7.65C42.26 171.65 42.17 171.46 42.09 171.26z"/>
more paths...
</g>
<g id="shots">
<use xlink:href="#ball" transform="translate(150,150) scale(1.0)" />
</g>
</g>
</svg>
I've been hacking on this for a few hours, and nothing I do impacts that green image. The outer rectangle fills the container just fine.
Thanks for your help!
The simplest way is to fix your viewBox attribute. You currently have it set to a width and height of 360, when your circle is only about 247 in diameter.
The top-left of the circle is at roughly (11, 9.5), so changing your viewBox to:
viewBox="11 9.5 247 247"
will cause it to fill your viewport.
How did I determine the dimensions of the circle? I used a little bit of javascript and called the getBBox() function on the element with id="green".
var b = document.getElementById("green").getBBox();
alert(b.x+" "+b.y+" "+b.width+" "+b.height);
Demo here

Resources