React Native svg clip path on image not working - reactjs

Trying to clip an Image component with an svg ClipPath is proving problematic. I can clip a Rect no problem, but when I replace the Rect with an Image, nothing shows up.
octogon.points = "80,0.3 23.6,23.6 0.3,80 23.6,136.4 80,159.7 136.4,136.4 159.7,80 136.4,2 3.6";
props.photoUri = "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fhalt-c46ef35c-1897-441e-840e-28147c0de5a9/ImagePicker/d68a7ddd-807e-4d26-95c2-bd47ddca803e.jpg"
<View style={styles.container}>
<Svg width={160} height={160} viewBox={`0 0 160 160`}>
<Defs>
<ClipPath id="clip">
<Polygon points={octogon.points} />
</ClipPath>
</Defs>
{/* <Rect x="0" y="0" width="160" height="160" fill="red" clipPath="#clip" /> */}
<Image x="0" y="0" width="160" height="160" source={{ uri: props.photoUri }} clipPath="#clip" />
</Svg>
</View>
The commented out Rect worked as intended and creates a red octogon. The Image returns blank.
I feel like I'm overlooking something simple. Any help is appreciated.

Answering my own question because I'm an idiot and hopefully it will help someone in the future. Be mindful of which components you are importing. I was using Image from 'react-native' instead of Image from 'react-native-svg'.
Once I swapped it over and changed source={{ uri: props.photoUri }} to href={{ uri: props.photoUri }}, it started working.

Related

Google maps Api SVG is not displayed in icons

SVG is not displayed in icons
Referenced sites
Add a background image (.png) to a SVG circle shape
https://codesandbox.io/s/react-google-maps-api-forked-pcup77?file=/src/index.js
source code
<LoadScript googleMapsApiKey="">
<GoogleMap
mapContainerStyle={containerStyle}
center={position}
zoom={17}
>
<Marker
position={position}
icon={{
url:
"data:image/svg+xml;utf-8, " +
'<svg width="100" height="100">' +
"<defs>" +
'<pattern id="image" patternUnits="userSpaceOnUse" height="100" width="100">' +
'<image x="0" y="0" height="100" width="100" xlink:href="http://i.imgur.com/7Nlcay7.jpg"></image>' +
"</pattern>" +
"</defs>" +
'<circle id="top" cx="50" cy="50" r="50" fill="url(#image)"/>' +
"</svg>",
}}
/>
</GoogleMap>
</LoadScript>
Is there a problem with SVG?
How to solve this problem?
I want to be able to display what I have created in SVG.

SVG prevent scaling when zooming page

I wanna know, is there any way to prevent scaling my SVG when zooming page in a browser?
Let's just say my SVG image is a measuring image and I want to keep the same size of my SVG independently from zoom in or zoom out page.
I'm using React
Style
svg: {
height: 150,
width: 150,
},
Example Code
<svg className={classes.svg} viewBox="0 0 150 150">
<g>
<circle cx={70} cy={70} r={32} fill="white" stroke="black"/>
<circle cx={70} cy={70} r={8} fill="black"/>
</g>
</svg>
You might use a viewport related unit like vw, vh.
<svg viewBox="0 0 150 150" style="width:5vw">
<g>
<circle cx="70" cy="70" r="32" fill="white" stroke="black"/>
<circle cx="70" cy="70" r="8" fill="black"/>
</g>
</svg>
Your svg element will keep it's initial size of 5vw.

react-icons apply a linear gradient

I would like to dynamically, partially fill a react-icons sourced Font Awesome Star using linear gradient. I have tried the following:
React Component with Inline Style - Setting the background of the parent span to gradient and making the SVG transparent. Can't seem to set the border around the SVG star to #FFFFFF so I see the parent span's whole background. See below:
import React from 'react'
import FaStar from 'react-icons/lib/fa/star'
const Stars = () => {
const inlineStyle = (pctFill) => {
return(
{background: 'linear-gradient(90deg, #134758 '+pctFill+'%, #d3d3d3 '+pctFill+'%)'}
)
}
return(
<div>
<span style={inlineStyle(50)}>
<FaStar />
</span>
</div>
)
}
export default Stars
I have also tried creating a linearGradient component and setting the path's fill="url(#component)", but react-icons path is the 3rd child to my parent span which I can't figure out how to access.
Please help
Was having the same issue, here's a simple working solution:
Add a < svg > element wrapping a < gradient > element to the component.
Add an id to the < gradient >
Link the gradient to the "stroke" property of the icon via "url(< id >)":
import { FiCheck } from 'react-icons/fi';
//...
<svg width="0" height="0">
<linearGradient id="blue-gradient" x1="100%" y1="100%" x2="0%" y2="0%">
<stop stopColor="#7a6ded" offset="0%" />
<stop stopColor="#591885" offset="100%" />
</linearGradient>
</svg>
<FiCheck style={{ stroke: "url(#blue-gradient)" }} />
obs: In some packs you may need to switch "stroke" to "fill".
<svg width="1em" height="1em">
<linearGradient id="blue-gradient" x1="100%" y1="100%" x2="0%" y2="0%">
<stop stopColor="#7a6ded" offset="0%" />
<stop stopColor="#591885" offset="100%" />
</linearGradient>
<FaFacebook style={{ fill: "url(#blue-gradient)"}}/>
My code worked in this way. Thanks a lot.
I think I found a solution, using additional svg and def tags. Only setback is that you must specify width and height of svg.
<Button className="border-0">
<svg width="20" height="20">
------------------------------- // add linearGradient
<defs>
<linearGradient id="myGradient" gradientTransform="rotate(90)">
<stop offset="5%" stopColor="gold" />
<stop offset="95%" stopColor="red" />
</linearGradient>
</defs>
--------------------------------------- //pass attr to react icon
<IconContext.Provider value={{ attr: {fill: "url('#myGradient')"}}}>
<FaInstagram />
</IconContext.Provider>
</svg>
</Button>
Hope this works!

React FabricJS Grouping (JSX)

NPM Package: https://www.npmjs.com/package/react-fabricjs
I'm using react-fabricjs and have a canvas with some icons showing. I'm now trying to get Grouping to work but I can't work out the syntax. Essentially I want to create this effect but using React JSX Code:
http://jsfiddle.net/anwjhs2o/1/
This is the code I have:
import React from 'react';
import {Canvas, Circle, Image, Path, Text, Rect, Ellipse, Triangle, Group} from 'react-fabricjs';
export default class CanvasFabric extends React.Component {
render() {
return (
<Canvas
ref="canvas"
width="556"
height="371"
>
<Circle
ref="circle"
radius={20}
left={100}
top={50}
stroke="green"
fill="blue"
blur={100}
color="rgba(0,0,0,0.6)"
/>
<Image
src="https://cloudinary-a.akamaihd.net/bountysource/image/twitter_name/d_noaoqqwxegvmulwus0un.png,c_pad,w_200,h_200,b_white/fabricjs.png"
width={64}
height={48}
left={10}
top={50}
/>
<Rect
ref="rect1"
width={50}
height={50}
left={150}
top={150}
fill="orange"
shadow="rgba(0,0,0,0.3) 5px 5px 5px"
/>
<Rect
ref="rect2"
width={60}
height={60}
left={145}
top={145}
stroke="purple"
strokeWidth={2}
blur={20}
/>
<Ellipse
ref="ellipse"
width={20}
height={100}
offsetX={350}
offsetY={250}
stroke="orange"
strokeWidth={2}
fill="yellow"
/>
<Triangle
ref="tri"
width={20}
height={20}
left={350}
top={250}
stroke="orange"
strokeWidth={1}
fill="black"
opacity={0.3}
/>
<Text text="Edit me"
top={300}
left={10}
shadow="rgba(0,0,0,0.3) 5px 5px 5px"
stroke="#ff1318"
strokeWidth={1}
fontStyle="italic"
fontFamily="Hoefler Text"
/>
</Canvas>
)
}
}
How could I say group the 2 Rect's - so they can be rotated/scaled etc together?
thankyou
Adam
** Extra Note: I'm no React Expert but I get the feeling the Fabric React Package is far from completed and this is why core functionality doesn't work.
I tried to check the lib, i did not get how to use the group.
The main point is you should just use fabricJS in a normal way even if you are using reactJS. Binding a fabricjs render to a react render may be slow or just unnecessary.
The group code is using:
While the Group constructor in fabric is different.
You can try 2 approaches, the only 2 that makes sense in react:
<Group>
<Rect
ref="rect1"
width={50}
height={50}
left={150}
top={150}
fill="orange"
shadow="rgba(0,0,0,0.3) 5px 5px 5px"
/>
<Rect
ref="rect2"
width={60}
height={60}
left={145}
top={145}
stroke="purple"
strokeWidth={2}
blur={20}
/>
</Group>
OR
<Group
objects={[<Rect
ref="rect1"
width={50}
height={50}
left={150}
top={150}
fill="orange"
shadow="rgba(0,0,0,0.3) 5px 5px 5px"
/>,
<Rect
ref="rect2"
width={60}
height={60}
left={145}
top={145}
stroke="purple"
strokeWidth={2}
blur={20}
/>]}
/>

Defs pattern with css module - modify point in c3.js line chart to have an image inside

I am using c3.js and my components are using CSS Modules. I wanted to modify the fill of points in the line chart with an image. For that in the render method I had added defs-pattern -
render(){
return (
<div>
<defs>
<pattern id="image" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1">
<image x="0" y="0" src="http://dummyimage.com/20x20/faf2fa/0011ff.png&text=x" />
</pattern>
</defs>
<C3Chart {...this.getConfig()}/>
</div>
);
}
In the styles css file I had added -
container :global(.c3-target-subscriber .c3-circle-5) {
fill: url(#image) !important;
}
But nothing happens. I just want to show an image inside the point of the line chart.
Any help is highly appreciated.
A <defs> element must have a parent that is a SVG element and not a HTML element. You need something like this:
<svg>
<defs>
<pattern id="image" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1">
<image x="0" y="0" src="http://dummyimage.com/20x20/faf2fa/0011ff.png&text=x" />
</pattern>
</defs>
<svg>
Also your CSS points to something with a id of gradient but your pattern's id is image.

Resources