SVG on React Native: react-native-svg-uri don't work for me - react-native

I see this post: https://stackoverflow.com/a/48245827/9775054
That was extracted from here, where says react-native-svg-uri.
But I can't make it work... I did all steps, but always says me that "Path './test.svg' could not be found.". I don't understand why, because the path to the file is correct for sure.
I installed correctly react-native-svg, react-native-svg-uri, babel-plugin-inline-import and I have put the config on .babelrc.
.babelrc config:
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["babel-plugin-inline-import", {
"extensions": [
".svg"
]
}]
]
}
Using the SVG File:
import * as React from 'react';
import SvgUri from 'react-native-svg-uri';
import testSvg from './test.svg';
export default () => (
<SvgUri
width="200"
height="200"
svgXmlData={testSvg}
/>
);
SVG File example
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#222FFF;}
</style>
<path class="st0" d="M48,96c26.5,0,48-21.5,48-48S74.5,0,48,0S0,21.5,0,48S21.5,96,48,96"/>
<path class="st0" d="M48,95c26,0,47-21,47-47S74,1,48,1S1,22,1,48S22,95,48,95"/>
<g>
<g id="Navigation">
<g>
<path class="st1" d="M24,30.9h48.6c1.8,0,3.2-1.5,3.2-3.3c0-1.8-1.4-3.3-3.2-3.3H24c-1.8,0-3.2,1.5-3.2,3.3
C20.8,29.4,22.2,30.9,24,30.9z M72.6,44.3H24c-1.8,0-3.2,1.5-3.2,3.3c0,1.8,1.4,3.3,3.2,3.3h48.6c1.8,0,3.2-1.5,3.2-3.3
C75.8,45.7,74.3,44.3,72.6,44.3z M72.6,64.2H24c-1.8,0-3.2,1.5-3.2,3.3c0,1.8,1.4,3.3,3.2,3.3h48.6c1.8,0,3.2-1.5,3.2-3.3
C75.8,65.6,74.3,64.2,72.6,64.2z"/>
</g>
</g>
</g>
</svg>
Other details
React Native verison: 0.57.8
Targeting Android 8.0
Someone could help me please?

Related

Svg Icon in expo react native appearing half or only a part of the icon

import * as React from 'react';
import { SvgXml } from 'react-native-svg';
export default function SvgComponent() {
const svgcode = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Iconly/Light-Outline/Profile">
<g id="Profile">
<g id="Group 3">
<mask id="mask0_33437_4900" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="4" y="14" width="16" height="8">
<path id="Clip 2" fill-rule="evenodd" clip-rule="evenodd" d="M4 14.4961H19.8399V21.8701H4V14.4961Z" fill="white"/>
</mask>
<g mask="url(#mask0_33437_4900)">
<path id="Fill 1" fill-rule="evenodd" clip-rule="evenodd" d="M11.9209 15.9961C7.65988 15.9961 5.49988 16.7281 5.49988 18.1731C5.49988 19.6311 7.65988 20.3701 11.9209 20.3701C16.1809 20.3701 18.3399 19.6381 18.3399 18.1931C18.3399 16.7351 16.1809 15.9961 11.9209 15.9961M11.9209 21.8701C9.96188 21.8701 3.99988 21.8701 3.99988 18.1731C3.99988 14.8771 8.52088 14.4961 11.9209 14.4961C13.8799 14.4961 19.8399 14.4961 19.8399 18.1931C19.8399 21.4891 15.3199 21.8701 11.9209 21.8701" fill="black"/>
</g>
</g>
<g id="Group 6">
<mask id="mask1_33437_4900" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="6" y="2" width="12" height="11">
<path id="Clip 5" fill-rule="evenodd" clip-rule="evenodd" d="M6.60986 2.00012H17.2299V12.6187H6.60986V2.00012Z" fill="white"/>
</mask>
<g mask="url(#mask1_33437_4900)">
<path id="Fill 4" fill-rule="evenodd" clip-rule="evenodd" d="M11.9209 3.42776C9.77989 3.42776 8.03789 5.16876 8.03789 7.30976C8.03089 9.44376 9.75989 11.1838 11.8919 11.1918L11.9209 11.9058V11.1918C14.0609 11.1918 15.8019 9.44976 15.8019 7.30976C15.8019 5.16876 14.0609 3.42776 11.9209 3.42776M11.9209 12.6188H11.8889C8.9669 12.6098 6.59989 10.2268 6.60989 7.30676C6.60989 4.38176 8.99189 1.99976 11.9209 1.99976C14.8489 1.99976 17.2299 4.38176 17.2299 7.30976C17.2299 10.2378 14.8489 12.6188 11.9209 12.6188" fill="black"/>
</g>
</g>
</g>
</g>
</svg>
`;
const Svg = () => (
<SvgXml
xml={svgcode}
width='set the width here'
height='set the height here'
/>
);
return <Svg />;
}
I am importing this and using it but the icon is appearing half what's the issue? The SVG is appearing properly in the browser. I have searched a lot but no help. Also tell if there is any other way to use svg in expo app
Not really sure but just a suggestion. Check if you have any other component getting rendered above your SVG.
Why I am guessing this is because since your phone is a relatively smaller device than your browser on a computer, any other component might get squashed thus forcing it to display above your SVG and you might be seeing it as if it's appearing half. On computer screens that might not be the case.
Let me know more about the issue so that I'm more clear about it.

SVG with path fill="url(xxx)" not working in Nuxt.js

The SVG (with animation) works perfect on .HTML file. But when I use it in Nuxt.js,
<path fill="url(#SVGID_82_)" ............. />
Everything tag that uses URL() for the fill attribute doesn't show up.
For example, the one with fill="#504D75" works fine, but the one with url(#SVGID_82_) is not visible.
This is how it should look like:
This is what it looks like in Nuxt.js:
This is part of the code:
<g>
<linearGradient
id="SVGID_82_"
gradientUnits="userSpaceOnUse"
x1="5022.084"
y1="484.3875"
x2="5051.5962"
y2="535.5038"
gradientTransform="matrix(-1 0 0 -1 5733.2881 656)"
>
<stop offset="0.2119" style="stop-color: #282447" />
<stop offset="0.2376" style="stop-color: #3f3b5f" />
<stop offset="0.2759" style="stop-color: #646085" />
<stop offset="0.2969" style="stop-color: #747195" />
</linearGradient>
<path
fill="url(#SVGID_82_)"
d="M695.75,129.58c0.73-0.4,1.81-0.48,2.7,0.14l25.91,14.94c1.18,0.68,2.14,2.34,2.14,3.7
l-0.09,30.43c0,0.68-0.24,1.15-0.63,1.37l-29.15,16.94c0.38-0.22,0.62-0.7,0.63-1.37l-0.3-30.46c0-1.36-0.81-2.61-2-3.29
l-26.24-15.67c-0.6-0.34-1.14-0.38-1.52-0.15L695.75,129.58z"
/>
<path
fill="#504D75"
d="M668.72,146.31c-1.18-0.68-2.15-0.13-2.15,1.23l-0.09,30.43c0,1.36,0.95,3.02,2.14,3.7l26.48,15.29
c1.18,0.68,2.15,0.13,2.15-1.23l0.09-30.43c0-1.36-0.95-3.02-2.14-3.7L668.72,146.31z"
/>
<g>
<path
fill="#282447"
d="M692.58,192.59l-21.68-12.52c-1.06-0.61-1.88-2.04-1.88-3.26l0.07-24.91c0-0.63,0.23-1.11,0.65-1.35
c0.42-0.24,0.95-0.2,1.51,0.12l-0.13,0.23l0.13-0.23l21.68,12.52c1.06,0.61,1.88,2.04,1.88,3.26l-0.07,24.91
c0,0.63-0.23,1.11-0.65,1.35c-0.18,0.1-0.38,0.15-0.59,0.15C693.21,192.87,692.9,192.77,692.58,192.59z M670.98,151.13
c-0.39-0.22-0.74-0.27-0.99-0.12c-0.25,0.14-0.38,0.46-0.38,0.9l-0.07,24.91c0,1.03,0.72,2.29,1.62,2.8l21.68,12.52
c0.39,0.22,0.74,0.27,0.98,0.12c0.25-0.14,0.38-0.46,0.38-0.9l0.07-24.91c0-1.03-0.72-2.29-1.62-2.8L670.98,151.13
L670.98,151.13z"
/>
</g>
</g>
I stumbled upon this issue once. Not sure if your use case is similar but should be.
Here, you do have an #SVGID_82_, and you are maybe having another element with this id (looping somewhere maybe), but you only can have one id per page in HTML. Hence, some are appearing while the other are not. Nonetheless to say that inspecting thanks to devtools is the best option so far here (try finding the missing paths).
As for my experience and solution.
worklife_wording.vue
<template>
<svg fill="none" viewBox="0 0 161 24">
<defs />
<path
fill="#32BFA3"
d="M.197 6.353a3.714 3.714 0 017.036-2.38l5.154 15.242a3.714 3.714 0 11-7.037 2.38L.197 6.352z"
/>
<path
fill="#FA9856"
fill-rule="evenodd"
d="M23.814 1.437a3.708 3.708 0 00-4.701 2.322l-1.328 3.919 3.867 11.434.044.14 4.441-13.113a3.708 3.708 0 00-2.323-4.702z"
clip-rule="evenodd"
/>
<path
:fill="`url(#prefix__prefix__paint${uniqueId}_linear)`" <------ here !
d="M8.724 6.145a3.714 3.714 0 117.037-2.38l5.153 15.242a3.714 3.714 0 11-7.036 2.379L8.724 6.145z"
/>
<path
fill="#144862"
d="M62....."
/>
<defs>
<linearGradient
:id="`prefix__prefix__paint${uniqueId}_linear`" <------- and here !
x1="7.584"
x2="22.122"
y1=".247"
y2="24.897"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#144862" />
<stop offset="1" stop-color="#3B7694" />
</linearGradient>
</defs>
</svg>
</template>
<script>
export default {
name: 'SvgWorklifeWording',
props: {
uniqueId: {
type: String,
default: '0',
},
},
}
</script>
I basically migrated my SVG into a .vue file and made it dynamic on the id part thanks to a prop. Then, I'm using it like this in my pages.
fancy-page.vue
<lazy-svg-unique-worklife-wording
unique-id="1"
></lazy-svg-unique-worklife-wording>
I do use native Nuxt lazy here and have a prefix of svg-unique for those specific component directory, on top of using nuxt-svg-loader.
Here is the config that I do use for those SVG in my nuxt.config.js components' section:
{
path: '~/assets/svg/unique_ids_needed',
prefix: 'svg-unique',
extensions: ['vue'],
},
That way, I do not have any collision when a unique ID is needed because I can basically loop on an array and display unique SVG urls thanks to v-for's index!
If my answer is not helping, I guess that we will need some reproduction on codesandbox to go further.

How to show SVG files in react-native

I want to render images from SVG files generated by illustrator, I am using react-native 0.59, react-native-svg and react-native-svg-uri,
Here's my jsx:
<View style={styles.aboutSection}>
<SvgUri
width="150"
height="150"
source={require('../../assets/images/logo_blue.svg')}
/>
</View>
and my SVG file:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-574 823.3 20 14" style="enable-background:new -574 823.3 20 14;" xml:space="preserve">
<style type="text/css">
.st0{fill:#2A327B;}
</style>
<g>
<g transform="translate(-320.000000, -1983.000000)">
<g transform="translate(40.000000, 1680.000000)">
<path class="st0" d="M-284,1140.3c-7.4,0-10-7-10-7s3.4-7,10-7c6.7,0,10,7,10,7S-277.3,1140.3-284,1140.3L-284,1140.3z
M-284,1129.3c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S-281.8,1129.3-284,1129.3L-284,1129.3z M-284,1135.3c-1.1,0-2-0.9-2-2
s0.9-2,2-2s2,0.9,2,2S-282.9,1135.3-284,1135.3L-284,1135.3z"/>
</g>
</g>
</g>
</svg>
And is not showing when I debug, what I am missing and is there a better way to show images from SVG files?
Is converting them to jsx using SVGR is a better approach or there are other ways to do so.
Since the package seems to be no more maintained, after a good time of searching around, I’ve eventually ended up with using custom web fonts with the help of react-native-icons:
(Optional) Minimizing the size of SVG, I used for this purpose SVG minizer
Convert fonts using icomoon
Add generated font to assets/fonts folder in your root (or any other path)
Add a linker in your packages.json
"rnpm": {
"assets": [
"./assets/fonts/"
]
}
And link it using react-native link
To create a custom icon component I’ve used react-native-icons, it
has a createIconSetFromIcoMoon function to render font generated from IcoMoon, and also a one generated from Fontello
In my custom component MyIcon.js, I also add the selection.json generated.
import { createIconSetFromIcoMoon } from 'react-native-vector-icons';
import MyIconConfig from '../../../selection.json';
const MyIcon = createIconSetFromIcoMoon(MyIconConfig, 'MyIcon-icons', 'MyIcon-icons.ttf');
//name of font I used in the website to generate font and name of ttf files generated
export default MyIcon;
I use it in my component, I the names of icons I've found them in demo.html:
<MyIcon
style={styles.customStyle}
name="previous"
size={18}
color=’red’
/>
Note: Make sure you use version >6.3.0 of react-native-icons, and link your assets by running:
react-native link ./assets/fonts/

Svg icon displays differently on ios and android

I have an svg icon uploaded on fontello
if is being displayed perfectly on ios
but on android there are a lot of spaces
any idea why?
this is my svg file
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 71.8 73.9" style="enable-background:new 0 0 71.8 73.9;" xml:space="preserve">
<g>
<g>
<path d="M38.1,36V2.1C38.1,0.9,37.1,0,36,0c-1.2,0-2.1,0.9-2.1,2.1V36c-4.8,1-8.5,5.2-8.5,10.3s3.6,9.4,8.5,10.3v15.1
c0,1.2,0.9,2.1,2.1,2.1c1.2,0,2.1-0.9,2.1-2.1V56.7c4.8-1,8.5-5.2,8.5-10.3C46.5,41.3,42.9,37,38.1,36z M36,52.7
c-3.5,0-6.4-2.9-6.4-6.4c0-3.5,2.9-6.4,6.4-6.4c3.5,0,6.4,2.9,6.4,6.4C42.4,49.9,39.5,52.7,36,52.7z"/>
<path d="M12.6,18.6V2.1c0-1.2-0.9-2.1-2.1-2.1S8.5,0.9,8.5,2.1v16.5C3.6,19.6,0,23.8,0,28.9s3.6,9.4,8.5,10.3v32.5
c0,1.2,0.9,2.1,2.1,2.1s2.1-0.9,2.1-2.1V39.3c4.8-1,8.5-5.2,8.5-10.3S17.4,19.6,12.6,18.6z M10.5,35.3c-3.5,0-6.4-2.9-6.4-6.4
c0-3.5,2.9-6.4,6.4-6.4s6.4,2.9,6.4,6.4C16.9,32.5,14,35.3,10.5,35.3z"/>
<path d="M63.3,18.6V2.1c0-1.2-0.9-2.1-2.1-2.1c-1.2,0-2.1,0.9-2.1,2.1v16.5c-4.8,1-8.5,5.2-8.5,10.3s3.6,9.4,8.5,10.3v32.5
c0,1.2,0.9,2.1,2.1,2.1c1.2,0,2.1-0.9,2.1-2.1V39.3c4.8-1,8.5-5.2,8.5-10.3S68.2,19.6,63.3,18.6z M61.3,35.3
c-3.5,0-6.4-2.9-6.4-6.4c0-3.5,2.9-6.4,6.4-6.4c3.5,0,6.4,2.9,6.4,6.4C67.6,32.5,64.8,35.3,61.3,35.3z"/>
</g>
</g>
</svg>
Add <svg width="71.8" height="73.9" props (or any other value keeping the same ratio).

Import String and convert to JSX in Expo

I would like to import a file as a String. Edit it. Then convert it to a JSX element.
Specifically, one use-case would be to import an svg file. Edit it so that it's compatible with React Native. Then convert it to a JSX element that can be reused.
I can't seem to get a string from importing .svg files and I would prefer not to change it to .txt as other projects already use these files and we also need to keep things DRY.
How can I import this:
<svg xmlns="http://www.w3.org/2000/svg" width="24.25" height="26.52">
<defs>
<style>
.circle, .line {
stroke: #77bc1f;
stroke-linecap: round;
stroke-width: 3.48px;
}
.circle {
fill: none;
}
.line {
fill: #9f9;
}
</style>
</defs>
<title>Logo Icon</title>
<path class="circle" fill="none" d="m19.12166,7a10.27,10.27 0 1 1
-14,0"/>
<line class="line" fill="#9f9" x1="12.06166" y1="1.74"
x2="12.06166" y2="14.88"/>
</svg>
And convert it into this:
<Svg width={24.25} height={26.52}>
<Path
class="circle"
fill="none"
d="m19.12166,7a10.27,10.27 0 1 1 -14,0"
stroke="#77bc1f"
strokeLinecap="round"
strokeWidth="3.48px"
/>
<Line
class="line"
stroke="#77bc1f"
strokeLinecap="round"
strokeWidth="3.48px"
fill="#000"
x1="12.06166"
y1="1.74"
x2="12.06166"
y2="14.88"
/>
</Svg>
Dynamically?
Great question. I never thought about with react native. I know with react you can do dangerouslySetInnerHTML. Please let me know if this works for you with rwact-native.
If doesn't may be try this from
https://medium.com/#remarkablemark/an-alternative-to-dangerously-set-innerhtml-64a12a7c1f96
Now to import the svg, there are multiple options to do that
Option 1. Use react-native-remote-svg
For example
import Image from 'react-native-remote-svg';
const SVGComponent = '<svg width="48px" height="1px" viewBox="0 0 48 1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><rect id="Rectangle-5" x="25" y="36" width="48" height="1"></rect></svg>';
<Image
source={{
uri: "data:image/svg+xml;utf8," + SVGComponent
}}/>
Option 2:
Use WebView
<WebView
source={{ html: svgstring }}
/>