Convert svg to react-native svg - javascript

I have the following svg code and I want to convert it to react-native-svg. How is it done correctly?
<svg width=200 height=200>
<defs>
<marker id="markerArrow1" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" />
</marker>
</defs>
<line x1="10" y1="10" x2="100" y2="100" style="stroke:#006600; marker-end: url(#markerArrow1)" />
</svg>

react-native-svg is an amazing package that has only a few differences. First you need to validate everything you're using is supported.
Going through the documentation you'll find that most things just have a difference in capitalization.
At present, Marker is not supported (check the ToDo's in the documentation). If you can be good to go.

You could use react-native-remote-svg, that would allow you to load any SVG code.
import React from 'react';
import Image from 'react-native-remote-svg';
class MyView extends React.Component {
render() {
const render =
"<svg width=200 height=200>" +
"<defs>" +
'<marker id="markerArrow1" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">' +
'<path d="M2,2 L2,11 L10,6 L2,2" />' +
"</marker>" +
"</defs>" +
'<line x1="10" y1="10" x2="100" y2="100" style="stroke:#006600; marker-end: url(#markerArrow1)" />' +
"</svg>";
return (
<Image
style={{ flex:1 }}
source={{
uri: "data:image/svg+xml;utf8," + render
}}
/>
);
}
Which gives me this image:

Related

SVG getBoundingClientRect() + "transform: rotate()" is bugged in Chrome in a very specific way

getBoundingClientRect() works fine on all SVG elements except in the circumstance when an element is rotated in Chrome.
Below I have drawn 2 lines, the one on the left is diagonal and the right line starts vertical, as represented by the black lines. The green box is a visual representation of the getBoundingClientRect(). I then apply the same transform rotate to both lines at the same time and then update the bounding box visual.
As you can see from the following, the left bounding box does not represent the actual bounds, however, the right one does.
The problem is I need the true client bounds of the line in whatever orientation it is. This works fine in Firefox. Does anyone know of another way to get or calculate the bounds when a line, specifically, has a transform rotate?
I have posted a copy of this here: getBoundingClientRect() + "transform: rotate()" is bugged in Chrome?. To help people with a similar problem, but then decided I'd actually ask the community.
Chrome: v100.0.4896.75
This bug has now been reported to the cromium bugs board here: https://bugs.chromium.org/p/chromium/issues/detail?id=1314959
UPDATE: I've added the same 2 static lines with a direct transform attribute with a rotation of 40deg, and 2 div's representing the 'getBoundingClientRect'. The left box is clearly not showing the smallest rectangle which contains the entire element.
UPDATE 2 Included a BBox Visual in blue. getBBox() simply calculates the bounds of a child relative to the SVG element itself, prior to any rotation transforms. getBoundingClientRect does calculate the transform correctly, but is using the BBox, which has it's own issues here: https://bugs.chromium.org/p/chromium/issues/detail?id=377665
let l = [1,2,3,4,5,6].map(d => document.getElementById(`line${d}`)),
vis = [1,2,3,4,5,6].map(d => document.createElement(`div${d}`)),
bboxvis = [1,2,3,4,5,6].map(d => document.createElement(`div${d}`)),
r = 0;
vis.map((element) => {
document.body.appendChild(element)
element.style.position = "absolute"
element.style.border = "1px solid green"
element.style.background = `#0FF0002e`
})
bboxvis.map((element) => {
document.body.appendChild(element)
element.style.position = "absolute"
element.style.border = "1px solid blue"
element.style.background = `#0000FF2e`
})
let updateBounds = (element, displayElement, bboxvisEl) => {
let rect = element.getBoundingClientRect(),
svgBounds = element.parentElement.getBoundingClientRect(),
bbox = element.getBBox(),
d = document.documentElement;
displayElement.style.top = rect.y+d.scrollTop+"px"
displayElement.style.left = rect.x+d.scrollLeft+"px"
displayElement.style.width = rect.width+"px"
displayElement.style.height = rect.height+"px"
bboxvisEl.style.top = bbox.y+svgBounds.y+d.scrollTop + "px"
bboxvisEl.style.left = bbox.x+svgBounds.x+d.scrollLeft +"px"
bboxvisEl.style.width = bbox.width+"px"
bboxvisEl.style.height = bbox.height+"px"
}
[3,4,5].forEach(i => {
updateBounds(l[i], vis[i], bboxvis[i]);
bboxvis[i].style.transform = `rotate(40deg)`;
})
setInterval(() => {
[0,1,2].forEach(i => {
l[i].setAttribute("transform", `rotate(${r} 80 80)`);
bboxvis[i].style.transform = `rotate(${r}deg)`;
updateBounds(l[i], vis[i], bboxvis[i]);
})
r++;
if(r===360) r=0;
}, 20)
.container {
width:140px;
height:140px;
display:inline-block;
}
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="40" y1="40" x2="120" y2="120" stroke="black" stroke-width="2"></line>
<line x1="40" y1="40" x2="120" y2="120" id="line1" stroke="red" stroke-width="2"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="80" y1="30" x2="80" y2="130" stroke="black" stroke-width="2"></line>
<line x1="80" y1="30" x2="80" y2="130" id="line2" stroke="red" stroke-width="2"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="60" y1="30" x2="100" y2="130" stroke="black" stroke-width="2"></line>
<line x1="60" y1="30" x2="100" y2="130" id="line3" stroke="red" stroke-width="2"></line>
</svg>
<br/>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="40" y1="40" x2="120" y2="120" id="line4" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="80" y1="30" x2="80" y2="130" id="line5" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="container">
<line x1="60" y1="30" x2="100" y2="130" id="line6" stroke="red" stroke-width="2" transform="rotate(40 80 80)"></line>
</svg>

React Native SVG Image not loading

I created an svg. And want to re-create it in React-Native. I use this npm package for it (https://www.npmjs.com/package/react-native-svg#image).
Here is the SVG
What i created is this
<TestApp
imageWidth={2300}
imageHeight={1438}
width={width}
url={'./url/to/picture'}
scale1={0.00100794}
scale2={0.000666667}
/>
const TestApp = ({
width,
overlayColor = 'black',
overlayOpacity = '0.3',
translate1,
translate2,
scale1,
scale2,
imageWidth,
imageHeight,
url,
}) => {
const height = (254 / 202) * width;
const translate = translate1
? `translate(${translate1} ${translate2 ? translate2 : ''})`
: '';
const scale = scale1 ? `scale(${scale1} ${scale2 ? scale2 : ''})` : '';
return (
<Svg
width={width}
height={height}
viewBox={`0 0 ${202} ${254}`}
fill="none"
>
<Mask
id="breathMask"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width={width}
height={height}
>
<Path
d="M0 0H201.374V228.761C201.374 228.761 158.683 254 100.687 254C42.6913 254 0 228.761 0 228.761V0Z"
fill="#C4C4C4"
/>
</Mask>
<G mask="url(#breathMask)">
<Rect
x="1"
width={width}
height={(303 / 254) * height}
fill="url(#pattern0)"
/>
<Path
d="M0 0H201.374V228.761C201.374 228.761 158.683 254 100.687 254C42.6913 254 0 228.761 0 228.761V0Z"
fill={overlayColor}
fillOpacity={overlayOpacity}
/>
</G>
<Defs>
<Pattern
id="pattern0"
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<Use href="#image0" transform={`${translate} ${scale}`} />
</Pattern>
<Image
id="image0"
widht={imageWidth}
height={imageHeight}
href="../path/to/url"
/>
</Defs>
</Svg>
);
};
Basically I copied the svg as it is.
The problem, the picture is not loading, even If I put a public url, such as this in it.
The svg with a grey background is not rendering. The picture will render in webview, though but not in ios or android.
You got any ideas how to fix it? Or a complete other way to achieve something like this?
Probably easiest way would be to just create a curved picture in photoshop, but thats not really dynamic.
Have you tried the using other parameters?
<Image
style={{ width: imageWidth, height: imageHeight }}
source={{
uri: '../path/to/url',
}}
/>

G-SVG doesnt show my Image inside it - react-native

I'm using react-native-svg. I want to show my image inside it but G doesnt show it:
<G x={endCoord2.x-widthHeight} y={endCoord2.y-widthHeight}>
<Image resizeMode='stretch' style={{width:50,height:50,margin:4}} source={{uri: 'https://javacupcake.com/wp-content/uploads/2017/07/IceCreamConeCupcakes_0307.jpg'}} />
</G>
but below code show a white circle:
<G x={endCoord2.x-widthHeight} y={endCoord2.y-widthHeight}>
<Circle r={widthHeight}
cx={widthHeight}
cy={widthHeight}
fill="#fff"
{...this._panResponderShops.panHandlers}
/>
</G>
where is my wrong?
solved:
you should import Image from react-native-svg:
<Image
x="5%"
y="5%"
width={widthHeight+20}
height={widthHeight+20}
preserveAspectRatio="xMidYMid slice"
opacity="0.5"
href={require('../../../images/ics/ic_blue_logo.png')}
clipPath="url(#clip)"
/>
https://github.com/react-native-community/react-native-svg/blob/master/README.md#image

How to mask user image in SVG hexagon shape on react native

I am struggling with hexagon shape on react native can anyone have some idea about how does it work using svg in react native or any alternate way?
creating shapes using js
image cutout of hexagon
masking image[enter image description here][1]
I'm trying this below image.
https://i.stack.imgur.com/MLDFl.jpg
This is My code:
render() {
return (
<Svg
height="300"
width="300"
viewBox="0 0 860 860"
>
<Defs>
<ClipPath id="clip">
<Polygon
strokeWidth="2"
stroke="#979797"
strokeDasharray='8,8'
strokeLinecap='butt'
fill="rgba(0, 0, 0, 0.5)"
points="258.5,223.999 130.5,298 2.5,224 2.5,76 130.5,2 258.5,76 " />
</ClipPath>
</Defs>
<Image
x="0%"
y="0%"
width="100%"
height="100%"
preserveAspectRatio="xMidYMid slice"
opacity="0.5"
href={require('./assets/Image.jpg')}
clipPath="url(#clip)"
/>
</Svg>
);
}
This kind of image can be created with my react-native-image-filter-kit module:
import { Image } from 'react-native'
import { DstATopComposition } from 'react-native-image-filter-kit'
const style = { width: 320, height: 320 }
const masked = (
<DstATopComposition
dstImage={
<Image
style={style}
source={{ uri: 'https://i.stack.imgur.com/MLDFl.jpg' }}
/>
}
srcImage={
<Image
style={style}
source={{ uri: 'http://www.myiconfinder.com/uploads/iconsets/256-256-53d5151ca4f467ed9951f85024881c85.png' }}
/>
}
/>
)
Note that shape generation is not supported currently, so you need to use another image for masking.

How to use markerEnd in react to draw an arrow

I want to draw an arrow with react. I found that maker-end is supported, see: React Docs. It is called markerEnd instead of marker-end. It expect a 'url(#markerArrow)' but it doesn't seem to work in react. How to make an arrow with svg and react?
Here is my approach in a component subclasses render function: It draws the line but not the arrow head.
render() {
return(
<div>
<svg className='Line' style={{ height:height, width:width, top:top, left:left }}>
<defs>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6"
orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" style={{fill: '#000000'}} />
</marker>
</defs>
<line x1={lx1} y1={ly1} x2={lx2} y2={ly2} markerEnd={ 'url(#markerArrow)' } style={{ stroke: 'red', strokeWidth: 2 }} />
</svg>
</div>
);
}
There should be an arrow on the bottom left of the red line.
keep your <defs> tag inside svg element
<defs>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" />
</marker>
</defs>
<svg width=200 height=200>
<line x1="10" y1="10" x2="100" y2="100" style="stroke:#006600; marker-end: url(#markerArrow)" />
</svg>
<svg width=200 height=200>
<defs>
<marker id="markerArrow1" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" />
</marker>
</defs>
<line x1="10" y1="10" x2="100" y2="100" style="stroke:#006600; marker-end: url(#markerArrow1)" />
</svg>
if this didnt work,try moving <defs> outside of react component and place in seperate svg in the page.you can check the implementation here
Just to help others who are looking for an implementation of marker-end in React:
Your code is totally correct!
There is most likely another problem. Perhaps a different element is on top of your <line>. You could check that for example by giving all of your elements an opacity attribute.

Categories

Resources