1

I create my image pattern like this:

    mainSVG
      .append('defs')
      .append('pattern')
      .attr('id', `pic${vertex.id}`)
      .attr('patternUnits', 'userSpaceOnUse')
      .attr('x', -vertex.radius)
      .attr('y', -vertex.radius)
      .attr('width', vertex.radius * 2)
      .attr('height', vertex.radius * 2)
      .append('image')
      .attr('fill', 'red')
      .attr('xlink:href', vertex.picture)
      .attr('width', vertex.radius * 2)
      .attr('height', vertex.radius * 2);

And I create my circle like this:

    node
      .enter()
      .append('g')
      .attr('class', 'node')
      .call(force.drag)
      .append('svg:circle')
      .attr('r', x => x.radius)
      .attr('id', x => `node${x.id}`)
      .attr('class', 'nodeStrokeClass')
      .attr('stroke', 'gray')
      .attr('stroke-width', '2')
      .attr('fill', x => `url(#pic${x.id})`)
      .on('mouseover', function(v) {
        d3.select(`#node${v.id}`)
          .transition()
          .attr('r', v.radius * 1.5);
      })
      .on('mouseout', function(v) {
        d3.select(`#node${v.id}`)
          .transition()
          .attr('r', v.radius);
      });

How can I have the image scale with the circle?

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
yukashima huksay
  • 5,834
  • 7
  • 45
  • 78

1 Answers1

2

The necessary changes are few:

  1. Instead of .attr('patternUnits', 'userSpaceOnUse'), do .attr('patternContentUnits', 'objectBoundingBox').
  2. Set both width and height of both the <pattern> and <image> to 1 (or 100%).

Here is the resulting demo (hover over the circle):

const mainSVG = d3.select('svg');

const defs = mainSVG.append('defs')
  .append('pattern')
  .attr('id', 'foo')
  .attr('width', 1)
  .attr('height', 1)
  .attr('patternContentUnits', 'objectBoundingBox')
  .append('image')
  .attr('xlink:href', 'https://cdn2-www.dogtime.com/assets/uploads/2010/12/senior-dog-2.jpg')
  .attr('preserveAspectRatio', 'none')
  .attr('width', 1)
  .attr('height', 1);

const circle = mainSVG.append('circle')
  .attr('r', 30)
  .attr('cx', 150)
  .attr('cy', 75)
  .attr('stroke', 'gray')
  .attr('stroke-width', '2')
  .attr('fill', 'url(#foo)')
  .on('mouseover', function() {
    d3.select(this)
      .transition()
      .attr('r', 70);
  })
  .on('mouseout', function() {
    d3.select(this)
      .transition()
      .attr('r', 30);
  });
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

You can read more about it in this excellent answer (not a duplicate, though).

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171