Setting rounded corners for svg:image

I was trying to make rounded corners for s svg:image (image embedded in SVG) with d3.js. I can't find out how to properly style the image, because according to W3C spec I should be able to use CSS, but neighter border nor rounded edges work for me.

Thanks in advance.

  vis.append("svg:image")
     .attr("width", width/3)
     .attr("height", height-10)
     .attr("y", 5)
     .attr("x", 5)      
     .attr("style", "border:1px solid black;border-radius: 15px;")
     .attr("xlink:href",
           "http://www.acuteaday.com/blog/wp-content/uploads/2011/03/koala-australia-big.jpg"); 

Edit:

Browsers tested: Firefox, Chrome


'border-radius' doesn't apply to svg:image elements (yet anyway). A workaround would be to create a rect with rounded corners, and use a clip-path.

An example.

The relevant part of the source:

<defs>
    <rect id="rect" x="25%" y="25%" width="50%" height="50%" rx="15"/>
    <clipPath id="clip">
      <use xlink:href="#rect"/>
    </clipPath>
  </defs>

  <use xlink:href="#rect" stroke-width="2" stroke="black"/>
  <image xlink:href="boston.jpg" width="100%" height="100%" clip-path="url(#clip)"/>

It's also possible to create several rect elements instead of using <use>.


For those just interested in making rounded avatars, here goes an example using d3 v4. Notice that you need to apply the clipping while the image is at (0,0), so you need to translate() the image to where you want it.

import { select } from 'd3-selection';

const AVATAR_WIDTH = 80;
const avatarRadius = AVATAR_WIDTH / 2;
const svg = select('.my-container');
const defs = this.svg.append("defs");
defs.append("clipPath")
  .attr("id", "avatar-clip")
  .append("circle")
  .attr("cx", avatarRadius)
  .attr("cy", avatarRadius)
  .attr("r", avatarRadius)
svg.append("image")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", AVATAR_WIDTH)
  .attr("height", AVATAR_WIDTH)
  .attr("xlink:href", myAvatarUrl)
  .attr("clip-path", "url(#avatar-clip)")
  .attr("transform", "translate(posx, posy)")
  .append('My username')

Another, easy alternative:

Wrap an html <img> tag in a <foreignObject> tag. This allows you to use normal html styling:

<foreignObject x='0' y='0' width='100px' height='100px'>
  <img
    width='100px'
    height='100px'
    src={'path/to/image.png'}
    style={{ borderRadius: '50%' }}
  />
</foreignObject>