I am trying fill a simple circle SVG with an image in React. The sources I found have not been helpful, for they don't seem to apply to JSX.
Here is the code I currently have:
import React, {Component} from 'react';
import Anime from '../images/Anime.jpeg';
class Circle extends Component {
render() {
return (
<div>
<svg height="300" width="300">
<circle cx="150" cy="150" r="100" stroke="black" stroke-width="3" fill={Anime} />
</svg>
</div>
);
}
}
export default Circle;
My first instinct was to tweak the fill attribute by either replacing the original color ="red" with ={Anime} or =url("../images/Anime.jpeg"), but neither worked.
(I know the path to the Anime image is correct, after testing it by rendering <img src={Anime} alt={Anime}></img> inside the div.
I see people using <defs> and <pattern> tags, as such (referring to this post):
<svg id="graph" width="100%" height="400px">
<!-- pattern -->
<defs>
<pattern id="image" x="0%" y="0%" height="100%" width="100%"
viewBox="0 0 512 512">
<image x="0%" y="0%" width="512" height="512" xlink:href="https://cdn3.iconfinder.com/data/icons/people-professions/512/Baby-512.png"></image>
</pattern>
</defs>
<circle id="sd" class="medium" cx="5%" cy="40%" r="5%" fill="url(#image)" stroke="lightblue" stroke-width="0.5%" />
</svg>
But these tags don't seem to work in React / JSX; I keep getting this error when I try to use them: Namespace tags are not supported by default. React's JSX doesn't support namespace tags. You can turn on the 'throwIfNamespace' flag to bypass this warning.
Is there a way around this? I want to be able to fit the following picture into a simple circle svg with a thick black border around it.
I figured out a way and wanted to post / share it, in case anyone is here, looking at this post and wondering what the (one of the) solution(s) is!
Here is my final code:
import React, {Component} from 'react';
import AnimeCropped from '../images/AnimeCropped.png';
class Circle extends Component {
render() {
return (
<div>
<svg height="670" width="670">
<circle cx="350" cy="350" r="300" stroke="black" stroke-width="5" fill="none" />
<image className='img-circle' xlinkHref={AnimeCropped} x='75.5' y="15" height="670" width="670"/>
</svg>
</div>
);
}
}
export default Circle;
Essentially what I did was:
Crop the photo to be a circle. I could have followed cubrr's recommendation above and clip-path'ed it (which is a great idea!), but instead - I just found and used a photo cropping tool online. I then named the newly-cropped picture "AnimeCropped" and saved it in the same directory.
Imported the picture into the component file and rendered via a <image> tag after the <circle> tag. It wasn't mentioned in my original question above, but I also hypothesized that inserting the image inside the circle might solve the problem. As such:
<svg height="670" width="670">
<circle cx="350" cy="350" r="300" stroke="black" stroke-width="5" fill="none">
<img src={AnimeCropped} alt={AnimeCropped}/>
</circle>
</svg>
But this didn't work.
In my final code, you'll see that the <image> tag comes after the <circle> tag, so technically, it's not really inside the circle, but just overlaying on top of it. Also note that I had to use <image>, not <img>. I'll have to do a bit of research on this, but <img> was giving me an error message.
Also important: In React, xlink:href won't work, but xlinkHref will! This really tripped me off, but I found this helpful post.
Using classNames, I edited the size of the cropped picture in my App.css file.
Configured the x- and y- coordinates so that it somewhat fits perfectly in the middle of the circle.
That's it! Just wanted to post this for closure / help me review what I learned.
Related
When you try to import any type of images inside React using the classical HTML it didn't work this is a big issue. So how to solve this problem?
<img src='./Image/Checked.png' height=50px width=50px/>
I spent a little bit of time researching this and I found 3 methods to solve this problem. This is why I made this Q&A style question. Hope to help other people like me out there to save some time.
Generally in HTML you will use this code
<img src='./Image/Checked.png' height=50px width=50px/>
But in React when you try to import assets like images you need a require tag. In the old versions it was enough to rewrite the code this way:
<img src={require('./Image/Checked.png')} height={50} width={50} />
The problem is that after a few updates the syntax changed a little bit and now for the images you need to use the default property to make it work. So with the new versions you actually have to use this code:
<img src={require('./Image/Checked.png').default} height={50} width={50} />
Another way to do the same think is to import the image and then use it this way:
import Image from './Image/Checked.png'
<img src={Image} height={50} width={50}/>
To finish in only case of svg images you can import them as React Component and use them this way:
import { ReactComponent as Image } from './Image/Checked.svg'
<Image />
I am building an application making use of #fluentui/react (version 8.34.7) and I am using create-react-app.
One of the things I would like to do is register custom icons which are in SVG format. Following the example here, I came up with the following code:
registerIcons({
icons: {
'hamburger-icon': (
<svg viewBox="0 0 16 16" role="presentation" focusable="false" aria-hidden="true">
<g>
<path d="M1 4.5v-1h14v1zm0 4v-1h14v1zm0 4v-1h14v1z"></path>
</g>
</svg>
)
}
});
and this works perfectly fine. I can reference hamburger-icon in my code and get the icon to display.
However, the issue with the code above is that I have to include svg file contents in my code. What I would like to do is read the SVG file contents and then use it in registerIcons method. I am not sure how I can do that.
If I do something like:
import Hamburger from 'assets/images/hamburger.svg';
I get a URL.
If I do something like:
import {ReactComponent as HamburgerIcon} from 'assets/images/hamburger.svg';
I get a React component whereas registerIcon method expects a React element.
Is it possible to simply specify a file path of an SVG file and register icon from that?
Well, it was ridiculously simple! All I had to do was this:
import {ReactComponent as HamburgerIcon} from 'assets/images/hamburger.svg';
registerIcons({
icons: {
'hamburger-icon': React.createElement(HamburgerIcon)
}
});
and all worked well.
I am using Next.js and next/image to display images, but the CSS is not working inside it. The image is in SVG format and I have placed it in the public folder. I am using Tailwind CSS along with this.
<Image
className="mt-3"
data-testid="close-icon"
src="/CloseIcon.svg"
alt="Close Nav Bar"
height="24"
width="24"
/>
I am not sure why it is not working and it is not being reflected in the browser. Any help will be greatly appreciated!
Before Next.js 12.2
Styling the next/image component's margins this way doesn't work in older Next.js versions. See relevant GitHub discussion for more details.
Internally to the next/image component, the <img> element and the elements that wrap it have inline styles that override certain values passed through className.
As a workaround, you can add a wrapper element and apply the margin styling to it instead.
<div className="mt-3">
<Image
data-testid="close-icon"
src="/CloseIcon.svg"
alt="Close Nav Bar"
height="24"
width="24"
/>
</div>
From Next.js 12.2
You can use the next/future/image component instead. This new component renders a single <img> element without any additional wrappers by default, and is no longer constrained by the wrapper's styles override.
You can enable next/future/image in next.config.js.
module.exports = {
experimental: {
images: {
allowFutureImage: true
}
}
}
From Next.js 13
The next/future/image component has been converted to next/image. Like next/future/image, this component renders a single <img> element and can be styled directly with className/styles.
Juliomalves's answer is right, but I would prefer:
<div className="mt-3" height="24" width="24">
<Image
data-testid="close-icon"
src="/CloseIcon.svg"
alt="Close Nav Bar"
layout="fill"
/>
</div>
You also can use a little cheat:
import {motion} from "framer-motion";
<motion.img
className="mt-3"
data-testid="close-icon"
src="/CloseIcon.svg"
alt="Close Nav Bar"
height="24"
width="24">
Try this:
<div style='width:104px;height:104px;position:relative;'>
<Image
alt='Mountains'
src='/mountains.jpg'
layout='fill'
objectFit='contain'
/>
</div>
More on objectFit Here
Wrapping the image component in a div helps solve the issue for me. I can apply the class name to the div and everything works as it should.
Please try to help me!
I need to render svg image from my folder "project/assest/images/test.svg" on android and ios view.
I have tried :
Solution 1 : <Image source={imagePath}></Image>
Solution 2 :
import SvgUri from 'react-native-svg-uri';
<View>
<SvgUri
width="200"
height="200"
source={{uri:'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg'}}
/>
</View>
Solution 3 : First i should, convert svg file to png,jpeg then render simple image, but that very weired way on view
Please help, what did i wrong in this.
You can also try react-native-svg package for SVG
For Example --
import * as React from 'react';
import { SvgUri } from 'react-native-svg';
export default () => (
<SvgUri
width="100%"
height="100%"
uri="http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"
/>
);
You can try with this
<SvgUri width="200" height="200" source={require('./project/assest/images/test.svg')} />
May this will help you
here are two ways to use SVG in react-native.
one way is to translate the SVG to JSX use this site.
the other way is to use a font instead of SVG directly:
firstly, use SVG files to generate font. I use this site. it is fontello.
then I use react-native-vector-icons to generate icon.
for more details, you can see its API
I use svg clipPath in my AngularJS project. I have a problem with specifying a relative url to the clipPath because i need to use the <base> element in my project.
For example this code works in a project without base, but not in a project with <base href="/">
<svg width="120" height="120"
viewPort="0 0 120 120" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="myClip">
<rect x="10" y="10" width="60" height="60"></rect>
</clipPath>
</defs>
<g clip-path="url(#myClip)">
<circle cx="30" cy="30" r="20"/>
<circle cx="70" cy="70" r="20"/>
</g>
</svg>
How can this be solved? I use ui-router, if that is relevant to the question...
This question is about the same, but the "solution" the OP found was to remove the base which isn't a solution in my case.
Change
<g clip-path="url(#myClip)">
So that you're using an absolute URL + a fragment identifier rather than just a fragment identifier on its own. E.g. url(http://mydomain.com/mypage#myClip)
You may be able to remove some parts e.g. the http and the domain if the base tag matches the absolute URL so /mypage#myClip might work.
In case anyone needs a function to do it here's one in pure JS:
It stores the original clipPath in the element data attribute and each time called, uses document.location.href to use absolute paths for url()
function fixClipPaths(svg, restore) {
Array.prototype.forEach.call(svg.querySelectorAll('*[clip-path]'), function (el) {
var clipUrl = el.getAttribute('clip-path');
if(!el.getAttribute('data-original-clip-path')) {
el.setAttribute('data-original-clip-path', clipUrl);
}
el.setAttribute('clip-path', 'url('+ (!restore ? document.location.href : '') + el.getAttribute('data-original-clip-path').substr(4));
});
}
// usage example
fixClipPaths(document.getElementsByTagName('svg')[0]);