Можно ли с помощью JavaScript изменить индекс / слой Z элемента SVG <g>? - PullRequest
80 голосов
/ 27 января 2009

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

Ответы [ 9 ]

108 голосов
/ 27 января 2009

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

31 голосов
/ 09 июня 2011

Альтернативой движущимся элементам в дереве является использование элементов <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>

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

См. скрипка .

21 голосов
/ 08 ноября 2011

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

В 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 == заменить себя == перерисовать

5 голосов
/ 06 марта 2015

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

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

... Нажмите на кнопки, чтобы «вытолкнуть» этот элемент вперед. (против перекраски всего набора и переноса 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>
4 голосов
/ 13 марта 2015

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

4 голосов
/ 27 января 2009

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

3 голосов
/ 16 января 2014

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

2 голосов
/ 05 октября 2016

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

$('g.element').remove().appendTo('svg');
1 голос
/ 26 августа 2016

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...