Могу ли я с помощью JavaScript изменить индекс / слой Z элемента SVG <g>?

85

Допустим, у меня есть пара составных фигур ( <g>). Я хочу иметь возможность щелкнуть и перетащить их, но я хочу, чтобы тот, который я перетаскиваю в данный момент, находился НАПЕРШЕ другого в Z-порядке, так что если я перетащу его на ДРУГОЙ, другой нужно затмить.

Кори Трейджер
источник
см. здесь .
Элиран Малка

Ответы:

113

Индекс Z в SVG определяется порядком появления элементов в документе. Вам нужно будет изменить порядок элементов, если вы хотите вывести определенную форму наверх.

Сэм
источник
1
@theonlygusti Элементы в конце документа находятся вверху. Если вы используете jQuery, вы должны иметь возможность использовать что-то вроде$('#thing-i-want-on-top').appendTo('#my-svg');
Адам Брэдли,
Так что, по сути, нет возможности переместить фигуру вверх (ось z) при наведении…?
chharvey
jQuery не поддерживает изменение порядка путей SVG.
Senthe
4
@chharvey, вы можете перемещать элементы вверх, переупорядочивая их - повторно добавляя. Вот элегантный пример: codepen.io/osublake/pen/YXoEQe
Фрейзер Киркман
36

Альтернативой перемещению элементов в дереве является использование <use>элементов, в которых вы изменяете xlink:hrefатрибут, чтобы он давал вам желаемый z-порядок.

Вот старая ветка в списке рассылки svg-developers, обсуждающая эту тему в контексте желания анимировать некоторые формы.

Обновить:

<svg xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink"
     style="width:100%; height: 100%">
    <circle id="c1" cx="50" cy="50" r="40" fill="lime" />
    <rect id="r1" x="4" y="20" width="200" height="50" fill="cyan" />
    <circle id="c2" cx="70" cy="70" r="50" fill="fuchsia" />
    <use id="use" xlink:href="#c1" />
</svg>

В этом примере элемент <use> является последним, что делает его самым передним элементом. Мы можем выбрать любой из других элементов в качестве переднего, просто изменив xlink:hrefатрибут. В приведенном выше примере мы выбрали круг с id="c1", что делает его самым верхним элементом.

Смотрите скрипку .

Эрик Дальстрём
источник
1
Этот ответ был бы гораздо полезнее с примером или с информацией из этого списка рассылки (который закрыт).
Kyeotic
3
Работает, но заставит вас добавить использование соответствующим образом. Если вы используете переводы, <use> понятия не имеет о них
Йохен Бедерсдорфер
@JochenBedersdorfer не уверен, что вы имеете в виду, как переводы связаны с z-порядком?
Эрик Дальстрем,
Это было не очень ясно. Если вы используете вложенные теги <g> с преобразованиями, вам необходимо преобразовать координаты с помощью getTransformToElement (..); (см. SVG-документы)
Йохен Бедерсдорфер
3
xlink:hrefустарело, теперь это простоhref
osvein
22

Это старый вопрос, но ...

В FireFox (7+) и Chrome (14+) вы можете вывести svg_element наверх. Это не дает вам свободы полного управления осью z, но это лучше, чем ничего;)

Просто добавьте этот элемент снова.

var svg = doc.createElemNS('svg');
var circle = doc.createElemNS('circle');
var line = doc.createElemNS('line');

svg.appendChild(circle); // appends it
svg.appendChild(line);   // appends it over circle
svg.appendChild(circle); // redraws it over line now

Я думал, что это вызовет ошибку или что-то в этом роде.

appendChild == заменить себя == перерисовать

CoR
источник
3
Вовсе не ошибка; appendChildсначала удаляет из старого родителя, если таковой имеется, даже если он такой же, как новый родитель, а затем добавляет его в список дочерних элементов нового родителя.
Potatoswatter
5

Другое решение, о котором не упоминалось, - это поместить каждый элемент / набор элементов svg в div. Вы можете легко изменить z-индекс div.

Fiddle: циклы элементов SVG с z-индексом для контейнеров

... Нажмите на кнопки, чтобы «сдвинуть» этот элемент вперед. (вместо перерисовки всего набора и перемещения 1 элемента на передний план, но сохраняя исходный порядок, как в принятом решении)

Было бы очень хорошо иметь относительные z-индексы ...

stackOverflow хочет, чтобы я поместил код, если это ссылка из jsfiddle? ... ook

Роман Рехлер
источник
5

Да, порядок - это то, что определяет, какой объект будет перед другим. Чтобы управлять порядком, вам нужно будет перемещать объекты в DOM. Хороший пример этого есть в вики по SVG по адресу https://www.w3.org/TR/SVG11/render.html#RenderingOrder.

Келли Андерсон
источник
4
Эта ссылка больше не работает. Эта ссылка объясняет ту же идею: ссылка
Стив
4

Если вы используете библиотеку svg.js , вы можете использовать команду «.front ()», чтобы переместить любой элемент наверх.

Эрел Сегал-Халеви
источник
3

SVGиспользует «модель рисования» рендеринга. Paint применяется к устройству вывода в последовательных операциях, так что каждая операция закрашивает некоторую область устройства вывода. Когда область перекрывает ранее окрашенную область, новая краска частично или полностью закрывает старую. - ссылка на это

Ишанк
источник
3

В SVG, чтобы получить больший индекс Z, вы должны переместить элемент вниз в дереве DOM. Вы можете сделать это с помощью jQuery, выбрав элемент SVG, удалив его и снова добавив в нужную позицию:

$('g.element').remove().appendTo('svg');
Агу Дондо
источник
2

Комментарий Адама Брэдли к ответу Сэма был точным. Он использует jQuery, а не только CSS, но он сказал следующее:

$('#thing-i-want-on-top').appendTo('#my-svg');

Однако для того, что я создавал, мне нужно, чтобы мой SVG-путь был выше любого другого пути при наведении, но все же был ниже моего SVG-текста. Итак, вот что я придумал:

$('#thing-i-want-on-top').insertBefore('#id-for-svg-text');

И appendTo, и insertBefore переместят ваш элемент в новое место, что позволит вам по желанию изменить глубину SVG-элемента.

ЧИСТАЯ ГРАФИКА
источник