Как заставить заливку рисунка SVG двигаться с объектом?

У меня есть несколько объектов SVG с мозаичным фоном изображения, используя fill="url(#background)где я определяю #background как pattern содержащий только image,

Однако, когда объект перемещается в настройках его x/y атрибуты (или cx/cyили что-либо еще, определяющее смещение), фон не перемещается вместе с ним.

Как мне сделать фон движением? Из Как бы я переместить шаблон SVG с элементом, который я пытался установить patternContentUnits='objectBoundingBox' но это просто превращает изображение в сплошной цветовой шарик (как ни странно, но окрашенный в соответствии с изображением, как если бы это был только первый пиксель или что-то подобное).

Вот jsfiddle, иллюстрирующий все это - верх rect был превращен в сплошной цвет, а затем снизу rect имеет фоновое изображение, но оно не движется с rect:

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

Я знаю, что если бы вы использовали transform="translate(...)" вместо установки x/y атрибуты, фон тоже переводится, но существующая кодовая база, в которой я работаю, не использует translate для позиционирования (и это будет иметь другие непредвиденные последствия для остальной части приложения).

Заранее благодарю за любую помощь.

3 ответа

Я на самом деле столкнулся с той же проблемой и нашел решение. Я раздвоил твою скрипку, чтобы показать изменения. По сути, вы удаляете атрибут patternContentUnits, поскольку он здесь не помогает, и обновляете атрибут x изображения, чтобы он соответствовал атрибуту объекта rect после каждого обновления.

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

Обновленный 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>

Обновлен JS:

var i = 0;
var newX;
setInterval(
    function(){
        $('rect').attr('x', Math.sin(i+=.01)*100+100);      
        $('#pat1').attr('x', $("#rect1").attr('x'));
    }, 100);

Если вы используете объекты objectBoundingBox, то ширина 1 (или 100%) - это ширина объекта, поэтому 178 будет в 178 раз больше. Вы, вероятно, хотите

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

Это не заставит шаблон двигаться. Вам понадобится какое-то преобразование, чтобы сделать это. Если вы не можете положить его на <rect> может быть, вы можете сделать прямоугольник ребенком <g> элемент и преобразовать <g> элемент вместо

Попробуйте установить значение patternUnits в "objectBoundingBox".

Используйте "вложенный документ SVG" для группировки перетаскиваемых элементов

положение шаблона относительно первого родительского документа SVG

играть здесь

<html>

<!-- svg.js + svg.draggable.js -->
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@latest/dist/svg.min.js"></script>
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.draggable.js@latest/dist/svg.draggable.min.js"></script>

<div id="canvas"></div>

<script type="text/javascript">

// create canvas
var draw = SVG().size(200, 200).addTo('#canvas')

// pattern of checkerboard
var patt = draw.pattern(20, 20)
patt.rect(20, 20).fill({color: '#fff'})
patt.rect(10, 10)
patt.rect(10, 10).move(10, 10)

// nested svg document
var nested = draw.nested()

// rect + pattern
nested.rect(80, 80).attr({
    fill: patt
})

// drag on
nested.draggable()



/*
// this works too, but its slow:

// group + draggable
var group = draw.group().draggable()

// move handler
group.on('dragmove', (e) => {
  const {x, y} = e.detail.box
  patt.move(x, y)
})

// rect with pattern
var r = group.rect(80, 80).attr({
    fill: patt
})
*/

</script>
</html>
Другие вопросы по тегам