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

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

Ответ 1

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

Ответ 2

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

Здесь старый поток в почтовом списке svg-developers, обсуждающий этот вопрос в контексте необходимости анимации некоторых фигур.

Update:

<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", что делает его самым верхним элементом.

См. fiddle.

Ответ 3

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

В 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 == replace self == redraw

Ответ 4

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

Ответ 5

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

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

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

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

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

var orderArray=[0,1,2];
var divArray = document.querySelectorAll('.shape');
var buttonArray = document.querySelectorAll('.button');

for(var i=0;i<buttonArray.length;i++){
    buttonArray[i].onclick=function(){
        var localI = i;
        return function(){clickHandler(orderArray.indexOf(localI));};
    }();
}


function clickHandler(divIndex) {
     orderArray.push(orderArray.splice(divIndex, 1)[0]);
    orderDivs();
}

function orderDivs(){
    for(var i=0;i<orderArray.length;i++){
       divArray[orderArray[i]].style.zIndex=i;        
    }
}
svg {
    width: 100%;
    height: 100%;
    stroke: black;
    stroke-width:2px;
    pointer-events: all;
}
div{
    position:absolute;
}
div.button{
    top:55%;
    height:5%;
    width:15%;
    border-style: outset;
    cursor:pointer;
    text-align: center;
    background:rgb(175, 175, 234);
    
}
div.button:hover{
    border-style: inset;
    background:yellow;
    
}
div.button.first{
    left:0%;
}
div.button.second{
    left:20%;
}
div.button.third{
    left:40%;
}
<div class="shape">
    <svg>
    <circle cx="50" cy="50" r="40" fill="lime" />
    </svg>
</div>
<div class="shape">
    <svg>
        <rect x="4" y="20" width="200" height="50" fill="cyan" />
    </svg>
</div>
<div class="shape">
    <svg>
        <circle cx="70" cy="70" r="50" fill="fuchsia" />
    </svg>
</div>

<div class='button first'>lime</div>
<div class='button second'>cyan</div>
<div class='button third'>fuchsia</div>

Ответ 6

Если вы используете svg.js library, вы можете использовать команду ".front()" для перемещения любого элемента в начало.

Ответ 7

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

Ответ 8

Комментарий Адама Брэдли к ответу Сэма был точно на месте. Он использует только 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.

Ответ 9

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

$('g.element').remove().appendTo('svg');