09fruits
09fruits

Reputation: 253

React JSX - Filling an svg with an image

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.

enter image description here

Upvotes: 2

Views: 3082

Answers (1)

09fruits
09fruits

Reputation: 253

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:

  1. 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.

  2. 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.

  1. Using classNames, I edited the size of the cropped picture in my App.css file.

  2. 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.

Upvotes: 2

Related Questions