How to show SVG files in react-native - 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/

Related

Some SVGs do not get rendererd in PDF using wkhtmltopdf

we are at the end of our knowledge.
We are using a twig template that is generating a html page which is then rendered by wkhtmltopdf as a PDF on an Ubuntu 18.04 machine.
The current issue is, that we also moved a lot of old EPS files to SVG by using Inkscape and everything works as expected. The images are shown on the PDFs.
Now all our new images are created with AI and saved as well working SVGs like this one:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 411.02 411.02" style="enable-background:new 0 0 411.02 411.02;" xml:space="preserve">
<style type="text/css">
.st0{fill:#575756;}
.st1{fill:none;stroke:#575756;stroke-width:2.8347;stroke-linejoin:round;stroke-miterlimit:3.8637;}
.st2{fill:#A8A8A7;stroke:#FFFFFF;stroke-width:0.5536;stroke-linejoin:round;stroke-miterlimit:22.9256;}
.st3{fill:none;stroke:#FFFFFF;stroke-width:0.5536;stroke-linejoin:round;stroke-miterlimit:22.9256;}
.st4{fill:#DADADA;stroke:#FFFFFF;stroke-width:0.5536;stroke-linejoin:round;stroke-miterlimit:22.9256;}
.st5{fill:#FFFFFF;}
.st6{display:none;}
.st7{display:inline;}
.st8{font-family:'HelveticaNeueLTPro-Roman';}
.st9{font-size:29.5px;}
.st10{letter-spacing:2;}
.st11{letter-spacing:-2;}
</style>
<g id="elements">
<g>
<polygon class="st0" points="368.71,103 365.16,111.5 361.62,103 368.71,103 368.71,103 "/>
<polygon class="st0" points="368.71,78.61 365.16,70.11 361.62,78.61 368.71,78.61 368.71,78.61 "/>
<line class="st1" x1="365.16" y1="75.86" x2="365.16" y2="106.24"/>
</g>
<g>
<polygon class="st0" points="368.71,324.49 365.16,332.99 361.62,324.49 368.71,324.49 368.71,324.49 "/>
<polygon class="st0" points="368.71,203.75 365.16,195.25 361.62,203.75 368.71,203.75 368.71,203.75 "/>
<line class="st1" x1="365.16" y1="200.99" x2="365.16" y2="327.73"/>
</g>
<g>
<polygon class="st0" points="81.42,345.6 72.92,342.06 81.42,338.52 81.42,345.6 81.42,345.6 "/>
<polygon class="st0" points="349.57,345.6 358.08,342.06 349.57,338.52 349.57,345.6 349.57,345.6 "/>
<line class="st1" x1="352.33" y1="342.06" x2="78.19" y2="342.06"/>
</g>
<g>
<path class="st2" d="M118.14,334.55l-40.3-3.91l-4.91-5.86v-32.87h4.68v-54.02h-4.68v-32.87l4.91-5.86l40.3-3.91h227.47
c7.75,0,14.03,6.28,14.03,14.0
...
But those SVGs do not get rendered. There is always a white space and we tried all possible embed/img/iframe/object/... methods.
I know there could be several reasons but maybe someone encountered a similiar issue. If anything else is needed as information please let me know.
Thanks!
I had the same problem, my solution is :-
Add size internally to SVG.
In your example: width="411.02px" height="411.02px"
Answer use
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="411.02px" height="411.02px" viewBox="0 0 411.02 411.02" style="enable-background:new 0 0 411.02 411.02;" xml:space="preserve">
It may be difficult to see but here is the SVG you posted. I wont repeat the snippet but for others testing, mention the last <g> needs to be changed to </g></svg> and remove unfinished last section.
Showing just the top half of each A4 page (my default)
On the Left is the way it would appear printed from Microsoft Edge.
On the right is the WkhtmltoPDF output (wkhtmltox-0.12.6-1.mxe-cross-win64 in Windows 10) from the same page but with some noticeable problems.
You are using Ubuntu 18.04 thus depending on that compiled version may get different results.
You can see on the left I asked the SVG be placed in the <centre>
But on the right WkhtmltoPDF has offset it further right
However, this may be in part due to the second problem.
The Output on the left was at 1:1 scale, however to get similar proportions in Wkhtmltopdf I had to scale the x:y value 2:1 (which value is actually more units than the notional page width) anyway here is the code for that output.
<!DOCTYPE html><html><head><style>
body {background: transparent; width=794px}
</style></head><body>Hello<center>
<img src="testing.svg" width=822px height=411px />
<br>Figure 1</center><br>World</body></html>
command line wkhtmltopdf.exe --enable-local-file-access local.htm testing.pdf

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

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?

Why does Apache Batik rasterise SVG documents transcoded to a PDF when opacity is set to less than one?

I have noticed that when I use Apache Batik to transcode SVG documents to PDF's that have an opacity set to less than one Batik will create a raster version of the SVG and place it in the pdf instead. When dealing with print this is not desirable. Is there any reason Batik does this? Is there anyway to avoid this flattening of SVG documents regardless of their opacity?
Our code to create the transcoder:
PDFTranscoder pdfTranscoder = new PDFTranscoder();
pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, PIXEL_CONVERSION);
pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_AUTO_FONTS, false);
We then take the SVG which is returned form element.getEncodedData() as an SVG string.
TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(element.getEncodedData().getBytes()));
TranscoderOutput output = new TranscoderOutput(byteStream);
pdfTranscoder.transcode(input, output);
For opacity we edit the SVG adding a group. Consider the following svg: Note many markup tags have been removed to keep the example concise:
<svg>
<rect x="100" y="100" width="100" height="100" />
</svg>
We would edit this SVG to appear as
<svg>
<g opacity="0.5">
<rect x="100" y="100" width="100" height="100" />
</g>
</svg>

svg images and making the background transparent

How do you declare the background of an svg script image to be transparent?
If you're viewing in a browser then the background should be transparent automatically. At least it is in FF4 and the latest version of Chrome, but not in some older browsers (e.g. http://petercollingridge.co.uk/data-visualisation/mouseover-effects-svgs).
If you want the background to be semi-transparent then fill the space with a <rect> and set its opacity to a number between 0 and less than 1.
Even easier method is to delete all the data that is used in the file content
Here is a sample before:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="24.000000pt" height="24.000000pt" viewBox="0 0 24.000000 24.000000" preserveAspectRatio="xMidYMid meet">
Here is a sample after
<g transform="translate(0.000000,24.000000) scale(0.100000,-0.100000)" fill="#ff0000" stroke="none">
<path d=""/>
</g>
</svg>
Remove all the data between

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 }}
/>