How to make SVG image pattern fill move with objec

2019-04-07 23:45发布

I have some SVG objects with a tiled image background using fill="url(#background), where I'm defining #background as a pattern containing just an image.

However, when the object is relocated by settings its x/y attributes (or cx/cy, or whatever else defines the offset), the background does not move with it.

How do I make the background move as well? From How would I move an SVG pattern with an element I tried to set the patternContentUnits='objectBoundingBox' but that just turns the image into a solid color blob (oddly, though, colored according to the image, as if it were just the first pixel or some such).

Here is a jsfiddle illustrating all of this - the top rect has been turned into a solid color, and then bottom rect has the background image but it doesn't move with the rect:

http://jsfiddle.net/x8nkz/17/

I know that if you were using transform="translate(...)" instead of setting the x/y attributes, the background does get translated as well, but the existing codebase I'm working within doesn't use translate for positioning (and it would have other unintended consequences on the rest of the application).

Thanks in advance for any help.

3条回答
对你真心纯属浪费
2楼-- · 2019-04-08 00:19

I actually encountered the same problem and found a solution. I've forked your fiddle to show the changes. Basically, you remove the patternContentUnits attribute as it doesn't help here and update the x attribute of the image to match that of the rect object after each update.

http://jsfiddle.net/RteBM/2/

Updated HTML:

<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<title>basic pattern</title>
<defs>
    <pattern id="pat1" width="179" height="132" patternUnits="userSpaceOnUse">
         <image x="0" y="0" width="179" height="132" xlink:href="http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/honey_im_subtle.png"></image>
    </pattern>
    <pattern id="pat2" width="179" height="132" patternUnits="userSpaceOnUse">
        <image x="0" y="0" width="179" height="132" xlink:href="http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/honey_im_subtle.png"></image>
    </pattern>
</defs>
<rect id="rect1" x="0" y="0" width="179" height="132" fill="url(#pat1)"/>
<rect id="rect2" x="0" y="150" width="179" height="132" fill="url(#pat2)"/>
</svg>

Updated JS:

var i = 0;
var newX;
setInterval(
    function(){
        $('rect').attr('x', Math.sin(i+=.01)*100+100);      
        $('#pat1').attr('x', $("#rect1").attr('x'));
    }, 100);
查看更多
Bombasti
3楼-- · 2019-04-08 00:19

Try to set value of patternUnits to "objectBoundingBox".

查看更多
贼婆χ
4楼-- · 2019-04-08 00:28

If you use objectBoundingBox units then a width of 1 (or 100%) is the width of the object so 178 would be 178 times that. You likely want

<pattern id="pat1" width="179" height="132" patternUnits="userSpaceOnUse" patternContentUnits="objectBoundingBox">
    <image width="1" height="1" xlink:href="http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/honey_im_subtle.png"></image>
</pattern>

That won't make the pattern move though. You are going to need a transform of some sort to do that. If you can't put it on the <rect> maybe you can make the rect a child of a <g> element and transform the <g> element instead.

查看更多
登录 后发表回答