React and SVG sprite - javascript

I am using React, and I am trying to load a svg icon from a sprite. My sprite is like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol viewBox="0 0 28.3 28.3" id="square">
<path d="M.3 30.7h27L13.8 3.8zM126.3-51.7c-8.8 0-16 7.2-16 16s7.2 16 16 16 16-7.2 16-16-7.2-16-16-16z" />
<path d="M0 28.3h28.3L14.2 0 0 28.3zm5.3-3.2l8.9-17.7L23 25.1H5.3z" />
</symbol>
<symbol viewBox="0 0 28.3 28.3" id="circle">
<circle cx="14.2" cy="14.2" r="14.2" />
</symbol>
</defs>
</svg>
And I load it with:
<svg viewBox="0 0 28.3 28.3" className="App-icon">
<use xlinkHref="./sprite#square" />
</svg>
With no results. I made a sandbox as an example: https://codesandbox.io/s/l711v6j7v7

If you want to reference it as external resource you need to use the proper URL to the svg file and it needs to be publicly accessible. So in the codesandbox you need to move it to the public folder, so that you can access it in the browser via
https://codesandbox.io/s/l711v6j7v7/sprite.svg
Then you can reference it like this:
<use href="/sprite.svg#square" />
See this fork of your codesandbox.

For those where the SVG file is an existing/external svg file.
You probably have an existing SVG webpack loader which is not working with the concept of SVG sprites. Why? It generally needs a file reference/url to the sprite file or the SVG (nodes) must exist in the DOM (Solution below)
This works:
Transform the plain SVG to JSX (google html to jsx)
Create a new pure react component and simply return the transformed JSX in render() method
Import and include the created react sprite component
Now use the sprite symbol via <use><svg href="#symbolnameorid"></svg></use> You can use it without the file prefix now

Related

SVG is not render on IOS (render empty space)

I check my site in browserstack and on same IOS or MacOs device in
different times SVG can work or can render empty space
//SVG USAGE
<svg>
<use xlinkHref={`#${id}`} />
</svg>
//SVG
<svg
onClick={onClick}
className="top-controls-panel__icon top-controls-panel__icon--points"
x="0px"
y="0px"
viewBox="0 0 47.1 12.1"
xmlSpace="preserve"
data-ieadjustwidth="40%"
>
<path d="M0.4,6.1c0,3.1,2.5,5.6,5.6,5.6s5.6-2.5,5.6-5.6S9.1,0.5,6,0.5S0.4,3,0.4,6.1" />
<path d="M17.4,6.1c0,3.1,2.5,5.6,5.6,5.6s5.6-2.5,5.6-5.6c0,0,0,0,0,0c0-3.1-2.5-5.6-5.6-5.6S17.4,3,17.4,6.1L17.4,6.1" />
<path d="M35.4,6.1c0,3.1,2.5,5.6,5.6,5.6c3.1,0,5.6-2.5,5.6-5.6S44.1,0.5,41,0.5C37.9,0.5,35.4,3,35.4,6.1L35.4,6.1" />
</svg>
I use JavaScript and React, problem that sometimes on IOS or MacOS
an empty space is rendered instead of svg.
I dont have apple device and testing site on browserStack service
In other questions I found that size of SVG can influence for that SVG is not render, but I dont undestand how that sizes should calculate, if sizes indicated in CSS in percent?
Also I change <use href... to <use xlinkHref... it is not work for me.
Now I won't try use
img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'"
instead of SVG, or I should use another variant?

How do I render svg images in React Native?

I've tried "react-native-remote-svg" and "react-native-svg-image"; neither of them manage to render the SVG file.
How do I handle SVG in React-native?
Example code:
import SVGImage from 'react-native-svg-image'
const EmailLogo = require('../static/others/Email.svg');
// Render etc....
<ButtonContainer>
<Button bgColor={colors.darkTeal} txtColor={colors.whiteText}
onPress={this.onSignInPress.bind(this)}>
LOG IN WITH
</Button>
<SVGImage
style={{ width: 80, height: 80 }}
source={EmailLogo}
/>
</ButtonContainer>
Result: It's a white square when it should be an email logo.
How does one handle SVG's properly in React-native?
I've been through this struggle. react-native-svg-icon helped me out, but there were some additional things that i had to do, to make it work.
First of all, this library uses react-native-svg underneath. And you need to convert your svg files into SVG objects that this library understands.
If your open your svg file with editor, it will look something like this
<svg xmlns="http://www.w3.org/2000/svg" viewBox="170.5 200.5 18.6 23">
<defs>
<style>.a{fill:#444;}.b{fill:#07b57a;}</style>
</defs>
<g transform="translate(171 201)">
<path class="a" d="M18.1,22.5H-.5V-.5H18.1ZM.5,21.5H17.1V.5H.5Z"/>
<rect class="b" width="5.4" height="1" transform="translate(9 5.4)"/>
<path class="b" d="M4.4,7.3,3,5.9l.7-.7.7.7L6.6,3.7l.7.7Z"/>
<rect class="b" width="5.4" height="1" transform="translate(9 10.5)"/>
<path class="b" d="M4.4,12.4,3,11l.7-.7.7.7L6.6,8.8l.7.7Z"/>
<rect class="b" width="5.4" height="1" transform="translate(9 15.6)"/>
<rect class="b" width="2.5" height="1" transform="translate(3.2 15.6)"/>
</g>
</svg>
You need to convert it to something like this
entry: {
svg: (
<G transform="translate(171 201)">
<Path fill="#444444" d="M-152.4-178H-171v-23h18.6V-178z M-170-179h16.6v-21H-170V-179z" />
<Rect x="-161.5" y="-195.1" fill="#07B57A" width="5.4" height="1" />
<Path
fill="#07B57A"
d="M-166.1-193.2l-1.4-1.4l0.7-0.7l0.7,0.7l2.2-2.2l0.7,0.7L-166.1-193.2z"
/>
<Rect x="-161.5" y="-190" fill="#07B57A" width="5.4" height="1" />
<Path
fill="#07B57A"
d="M-166.1-188.1l-1.4-1.4l0.7-0.7l0.7,0.7l2.2-2.2l0.7,0.7L-166.1-188.1z"
/>
<Rect x="-161.5" y="-184.9" fill="#07B57A" width="5.4" height="1" />
<Rect x="-167.3" y="-184.9" fill="#07B57A" width="2.5" height="1" />
</G>
),
viewBox: '0 0 18.6 23',
}
This is a representation of the svg file in components of react-native-svg library. One thing you need to pay attention here, is viewbox of the svg file. I am not sure why, but most of the time, it is 'off center'. I will show in screenshots below. Because of that, it cannot be displayed by the react-native-svg-icon as well. To bring it to center you can use Adobe Illustrator, or some other online tool to edit svg. One i used is http://editor.method.ac/. So, I uploaded my svg, recentered it and downloaded it again. and used that svg file to create object in my react native code.
This is my initial svg file that i uploaded to the service. if you zoom out and press cmd+a (or ctrl+a) to select all, it will highlight svg icon, like in screenshot below. You should position it to the white part, either by dragging it, or by setting X and Y on top right corner to 0s.
This is how it will look when centered
Once you save that svg file, use it to convert it to javascript object with react-native-svg components, more info on that can be found here
Once you create you svg objects, you can use it with react-native-svg-icon. You will find how to do that in the link I shared above.
I know, this is a lot of pain and seemingly over complicated, and I spent quite some time to make it work, but it is the only way I managed to accomplish it.
One other option would be to convert your svgs into font icons with icomoon.com and use it with react-native-vector-icons. but it will only work if your svgs are drawn with only one color, as multicolored ones cannot be converted to fonts
P.S. I didn't try, but maybe, libraries that you tried to use might work with centered svg file that we got from online service. Let me know if it works, then it can be helpful to other users as well.
react-native-svg-image and react-native-svg-image uses WebView to render SVG files so it do not support local files at the moment. Its written it the docs.
Use react-native-svg-uri to render SVG images in React Native from an URL or a static file. to use react-native-svg-uri you will need to link react-native-svg as well. So read docs carefully.

Setting SVG preserveAspectRatio attribute dynamically

If you have an Angular component that uses svg files by referring to symbols from one packed file:
svg instance
<svg>
<use xlink:href="#my-symbol"></use>
</svg>
symbols as they appear in the imported file
<symbol id="my-symbol" viewBox="0 0 24 24">
<title>my-symbol</title>
<path class="path1" d=" ... data here ..."></path>
</symbol>
in order to get control over scaling behavior, every symbol element should apparently have preserveAspectRatio="..." set accordingly.
What if I want to do that dynamically, taking the values for preserveAspectRatio from component instance HTML input?
Something like:
imaginary my-icon template
<my-icon preserveAR="alignMeetOrSlice">
<svg preserveAspectRatio="{{preserveAR}}">
<use xlink:href="#my-symbol"></use>
</svg>
</my-icon>
desired render:
<svg>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://somedomain.com/my.svg#my-symbol"></use>
#shadow-root (user agent)
<svg id="my-symbol" viewBox="0 0 24 24"> <!-- attribute should go to this svg -->
...
</svg>
</svg>
I tried querySelector('symbol') on the container - but it returned null results.
Is there a method to get into the shadow root and modify the symbol element?
In JS you can use direct assignment for svg.preserveAspectRatio.baseVal.align.
Instead a preserveAspectRatio="none" in HTML
you can write svg.preserveAspectRatio.baseVal.align=1 or svg.setAttribute('preserveAspectRatio', 'none'); in an JS script.
The examples are presented here:
with code-generation
alternatively with HTML-injection
and available values for aspectRatio can be seen here

Getting external SVG file from React component

I am trying to use SVG icons on my React site using an external SVG file with all of my icons.
I am using the <use> tag and calling them from a component. However, I get a console error that the browser cannot get the SVG file (404). It is currently in the same folder as my component jsx file.
I have an external file called svgSprites.svg:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" >
<path id="icon-home" class="path1" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
<path id="icon-camera" class="path1" d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
</svg>
and in my component:
<svg>
<use xlinkHref="svgSprites.svg#icon-home"></use>
</svg>

JavaScript - Is there a way how to draw SVG path UNDER the content?

I need a path that goes UNDER the content (text) - is there a way how to do that?
(as already been answered somewhere else, z-index doesnt affect svg paths)
You can declare PATH and TEXT in different SVG layers, and put one layer onto another like this
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="position:absolute;z-index:1">
<text x="100" y="15" fill="red">I love SVG</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="position:absolute;z-index:0">
<path d="M150 0 L75 200 L225 200 Z" />
</svg>
http://jsfiddle.net/WJZrU/

Categories

Resources