Safari does not update textPath when path data is changed dynamically - svg

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>

Related

How to draw letter R with SVG

I have a svg of letter B here is the code:
<svg id="logo" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 84 96">
<title>Logo</title>
<g transform="translate(-8.000000, -2.000000)">
<g transform="translate(11.000000, 5.000000)">
<path
d="M45.691667,45.15 C48.591667,46.1 50.691667,48.95 50.691667,52.2 C50.691667,57.95 46.691667,61 40.291667,61 L28.541667,61 L28.541667,30.3 L39.291667,30.3 C45.691667,30.3 49.691667,33.15 49.691667,38.65 C49.691667,41.95 47.941667,44.35 45.691667,45.15 Z M33.591667,43.2 L39.241667,43.2 C42.791667,43.2 44.691667,41.85 44.691667,38.95 C44.691667,36.05 42.791667,34.8 39.241667,34.8 L33.591667,34.8 L33.591667,43.2 Z M33.591667,47.5 L33.591667,56.5 L40.191667,56.5 C43.691667,56.5 45.591667,54.75 45.591667,52 C45.591667,49.2 43.691667,47.5 40.191667,47.5 L33.591667,47.5 Z"
fill="currentColor"
/>
<polygon
id="Shape"
stroke="currentColor"
strokeWidth="5"
strokeLinecap="round"
strokeLinejoin="round"
points="39 0 0 22 0 67 39 90 78 68 78 23"
/>
</g>
</g>
</svg>
And here is how it looks
I just need to change letter B to letter R but i don't know the path and it should be centered in polygon
As I've commented: delete the path and add:
<text x="39" y="45" dominant-baseline="middle" text-anchor="middle" font-size="30">R</text>
where x="39" y="45" are the coords of the center of the hexagon. Please observe that the text is centered around this point (<text x="39" y="45" dominant-baseline="middle" text-anchor="middle")
svg{width:90vh}
<svg id="logo" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 84 96">
<title>Logo</title>
<g transform="translate(-8.000000, -2.000000)">
<g transform="translate(11.000000, 5.000000)">
<polygon
id="Shape"
stroke="currentColor"
strokeWidth="5"
strokeLinecap="round"
strokeLinejoin="round"
points="39 0 0 22 0 67 39 90 78 68 78 23"
fill="none"
/>
<text x="39" y="45" dominant-baseline="middle" text-anchor="middle" font-size="30">R</text>
</g>
</g>
</svg>
If you don't plan going down the rabit hole of SVG's, try to use a SVG builder, should be faster as easier to visualise.
Examples: https://vectorpaint.yaks.co.nz/
https://editor.method.ac/
After you finish you can download and use the svg file or open the file in your editor to see the code

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.

SVG `use` is rendering blank image

I am trying to use SVGs as CSS background images, and have everything working except for importing external files with use.
Here is what I have:
CSS and HTML:
.shape1 {
background: url("shapes/shape1.svg") no-repeat;
}
<div class="shape1"></div>
Then the shapes/shape1.svg file:
<svg viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg">
<path d="
M 10 10
l 0 180
" fill="none" stroke="#000" stroke-width="1px"/>
<use href="parts/part1.svg#build"/>
</svg>
It references the parts/part1.svg file, which contains this:
<svg viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="build" d="
M 90 10
l 0 180
" fill="none" stroke="#000" stroke-width="1px"/>
</defs>
</svg>
However, when I render everything, it only displays one line, not two.
I've tried a few things. I've tried removing the defs and just loading directly, like this:
<svg viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg">
<path d="
M 10 10
l 0 180
" fill="none" stroke="#000" stroke-width="1px"/>
<use href="parts/part1.svg"/>
</svg>
<svg viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg">
<path d="
M 90 10
l 0 180
" fill="none" stroke="#000" stroke-width="1px"/>
</svg>
I've also tried messing with the file paths. My directory structure is this:
index.html
shapes/
shapes/shape1.svg
parts/
parts/part1.svg
I've tried ../parts/part1.svg, etc.. Also, I am running this directly from the filesystem, so the path is: file:///Users/me/Desktop/test/index.html. I am getting no errors in the web console. Any help would be appreciated!
I am on Chrome and only care about this working on Chrome for now.
When SVG is used as an image the SVG file must be self-contained for privacy reasons.
So shape1.svg cannot access anything outside itself. You'd have to embed part1.svg into shape1.svg.
Alternatively don't use SVG as a background image, embed it via an object or iframe tag or have it inline.

Animate shape in typography mask 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>

Can strokes be used as part of clip-paths in SVGs?

I am in the middle of writing SVG output from MuPDF, and I've run up against what seems to be a limitation in the capabilities of SVG. I thought I'd ask here in case this was a known problem with a known workaround (or in case I'm doing something stupid!)
I have the following SVG:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="21.59cm" height="27.94cm" viewBox="0 0 600 600">
<path stroke-width="12" fill="none" stroke="#0000ff" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
<clipPath id="cp0">
<path stroke-width="12" fill="none" stroke="#000000" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
</clipPath>
<g clip-path="url(#cp0)">
<rect fill="#ff0000" x="0" y="0" width="600" height="600"/>
</g>
</svg>
This draws a stroked path (shaped like '[' in blue). Then it sets the same path to be a clipping path, and fills the clipping path in red.
I was hoping that the clipping path would be set to the stroked version of the path, and hence the red shape would exactly overwrite the blue one. In my tests here however, the "fill or strokedness" of the path is ignored, and the path is "filled" - hence I get a red square drawn within the blue shape.
Is there a way to get the behaviour I was hoping for? Or am I going to have to write code to manually flatten and stroke paths before outputting them to SVG?
Thanks in advance for any replies!
Clip-paths in svg are meant to be just the shape, not the traits of the shape, so in other words you'll not get the stroke included. What you can do is use a mask instead, setting the stroke of the path in the mask to white.
Here's an example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 600 600">
<defs>
<mask id="m0" maskUnits="userSpaceOnUse" x="0" y="0" width="600" height="600">
<path fill="none" stroke="white" stroke-width="5" d="M 150 300 L 80 300 L 80 370 L 150 370" />
</mask>
</defs>
<path stroke-width="12" fill="none" stroke="#0000ff" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
<g mask="url(#m0)">
<rect fill="yellow" x="0" y="0" width="600" height="600" />
</g>
</svg>

Resources