[javascript] SVG 요소 Z- 색인을 D3로 업데이트

D3 라이브러리를 사용하여 SVG 요소를 z 순서의 맨 위로 가져 오는 효과적인 방법은 무엇입니까?

내 특정 시나리오의 (a를 추가하여하는 하이라이트 파이 차트 stroke받는 path마우스가 주어진 조각 위에있을 때). 내 차트를 생성하는 코드 블록은 다음과 같습니다.

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .attr("fill", function(d) { return color(d.name); })
    .attr("stroke", "#fff")
    .attr("stroke-width", 0)
    .on("mouseover", function(d) {
        d3.select(this)
            .attr("stroke-width", 2)
            .classed("top", true);
            //.style("z-index", 1);
    })
    .on("mouseout", function(d) {
        d3.select(this)
            .attr("stroke-width", 0)
            .classed("top", false);
            //.style("z-index", -1);
    });

몇 가지 옵션을 시도했지만 지금까지 운이 없습니다. 둘 다 사용 style("z-index")하고 호출 classed해도 작동하지 않았습니다.

“상위”클래스는 내 CSS에서 다음과 같이 정의됩니다.

.top {
    fill: red;
    z-index: 100;
}

fill성명서는 올바르게 켜고 끄는 것을 확인하기위한 것입니다. 그것은.

사용하는 sort것이 옵션이라고 들었지만 “선택된”요소를 맨 위로 가져 오기 위해 어떻게 구현되는지 확실하지 않습니다.

최신 정보:

mouseover하이라이트를 표시하기 위해 이벤트 의 SVG에 새 호를 추가하는 다음 코드로 특정 상황을 수정했습니다 .

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .style("fill", function(d) { return color(d.name); })
    .style("stroke", "#fff")
    .style("stroke-width", 0)
    .on("mouseover", function(d) {
        svg.append("path")
          .attr("d", d3.select(this).attr("d"))
          .attr("id", "arcSelection")
          .style("fill", "none")
          .style("stroke", "#fff")
          .style("stroke-width", 2);
    })
    .on("mouseout", function(d) {
        d3.select("#arcSelection").remove();
    });



답변

개발자가 제시 한 솔루션 중 하나는 “D3의 정렬 연산자를 사용하여 요소를 재정렬”하는 것입니다. ( https://github.com/mbostock/d3/issues/252 참조 )

이 관점에서 데이터를 비교하여 요소를 정렬하거나 데이터가없는 요소 인 경우 위치를 정렬 할 수 있습니다.

.on("mouseover", function(d) {
    svg.selectAll("path").sort(function (a, b) { // select the parent and sort the path's
      if (a.id != d.id) return -1;               // a is not the hovered element, send "a" to the back
      else return 1;                             // a is the hovered element, bring "a" to the front
  });
})


답변

다른 답변에서 설명한 것처럼 SVG에는 Z- 색인 개념이 없습니다. 대신 문서의 요소 순서에 따라 도면의 순서가 결정됩니다.

요소를 수동으로 재정렬하는 것 외에도 특정 상황에 대한 다른 방법이 있습니다.

D3로 작업하면 항상 다른 유형의 요소 위에 그려야하는 특정 유형의 요소가 있습니다 .

예를 들어 그래프를 배치 할 때 링크는 항상 노드 아래에 배치되어야합니다. 일반적으로 일부 배경 요소는 일반적으로 다른 모든 요소 아래에 배치해야하며 일부 하이라이트 및 오버레이는 위에 배치해야합니다.

이러한 상황이 발생하면 해당 요소 그룹에 대한 상위 그룹 요소 를 만드는 것이 가장 좋은 방법 이라는 것을 알았습니다 . SVG에서는이를 위해 g요소를 사용할 수 있습니다 . 예를 들어 항상 노드 아래에 위치해야하는 링크가있는 경우 다음을 수행하십시오.

svg.append("g").attr("id", "links")
svg.append("g").attr("id", "nodes")

이제 링크와 노드를 그릴 때 다음과 같이 선택합니다 ( #요소 ID 참조로 시작하는 선택기 ).

svg.select("#links").selectAll(".link")
// add data, attach elements and so on

svg.select("#nodes").selectAll(".node")
// add data, attach elements and so on

이제 모든 링크는 항상 모든 노드 요소 앞에 구조적으로 추가됩니다. 따라서 SVG는 요소를 추가하거나 제거하는 빈도와 순서에 관계없이 모든 노드 아래의 모든 링크를 표시합니다. 물론 동일한 유형 (즉, 동일한 컨테이너 내)의 모든 요소는 추가 된 순서를 따릅니다.


답변

SVG에는 Z- 색인이 없지만 DOM 요소의 순서를 사용하므로 다음을 수행하여 앞쪽으로 가져올 수 있습니다.

this.parentNode.appendChild(this);

그런 다음 예를 들어 insertBefore 를 사용 하여 다시 넣을 수 있습니다 mouseout. 그러나이를 위해서는 요소가 이전에 삽입되어야하는 형제 노드를 대상으로 할 수 있어야합니다.

데모 : JSFiddle 살펴보기


답변

SVG는 Z- 색인을 수행하지 않습니다. Z 순서는 컨테이너에있는 SVG DOM 요소의 순서에 따라 결정됩니다.

내가 말할 수있는 한 (그리고 과거에 이것을 여러 번 시도 했음) D3는 단일 요소를 맨 앞으로 가져 오기 위해 분리하고 다시 연결하는 방법을 제공하지 않습니다.

선택 항목에 나타나는 순서와 일치하도록 노드를 다시 섞는 .order()방법 이 있습니다 . 귀하의 경우에는 단일 요소를 맨 앞으로 가져와야합니다. 따라서 기술적으로 원하는 요소를 앞에두고 (또는 마지막에 맨 위에있는 요소를 기억할 수 없음) 선택 사항을 재 지정한 다음 호출 order()할 수 있습니다.

또는이 작업을 위해 d3를 건너 뛰고 일반 JS (또는 jQuery)를 사용하여 단일 DOM 요소를 다시 삽입 할 수 있습니다.


답변

간단한 대답은 d3 주문 방법을 사용하는 것입니다. d3.select ( ‘g’). order () 외에도 버전 4 에는 .lower ().raise () 가 있습니다. 이는 요소가 나타나는 방식을 변경합니다. 자세한 정보는 문서를 참조하십시오-https: //github.com/d3/d3/blob/master/API.md#selections-d3-selection


답변

나는 내 코드에 futurend의 솔루션을 구현했고 작동했지만 내가 사용하고 있던 많은 수의 요소로 인해 매우 느렸다. 내 특정 시각화를 위해 더 빠르게 작동하는 jQuery를 사용하는 대체 방법이 있습니다. 공통된 클래스를 갖는 위에 원하는 svg에 의존합니다 (제 예에서 클래스는 내 데이터 세트에서 d.key로 표시됩니다). 내 코드에는 <g>내가 재구성하는 모든 SVG를 포함하는 “위치”클래스가 있습니다.

.on("mouseover", function(d) {
    var pts = $("." + d.key).detach();
    $(".locations").append(pts);
 });

따라서 특정 데이터 포인트 위로 마우스를 가져 가면 코드는 해당 특정 클래스가있는 SVG DOM 요소가있는 다른 모든 데이터 포인트를 찾습니다. 그런 다음 해당 데이터 포인트와 관련된 SVG DOM 요소를 분리하고 다시 삽입합니다.


답변

완전히 새로운 답변을 작성하는 대신 @ notan3xit이 답변 한 내용을 확장하고 싶었습니다 (하지만 평판이 충분하지 않습니다).

요소 순서 문제를 해결하는 또 다른 방법은 그릴 때 ‘추가’대신 ‘삽입’을 사용하는 것입니다. 이렇게하면 경로가 항상 다른 svg 요소 앞에 함께 배치됩니다 (이는 코드가 이미 다른 svg 요소에 대해 enter () 전에 링크에 대해 enter ()를 수행한다고 가정합니다).

d3 삽입 API : https://github.com/mbostock/d3/wiki/Selections#insert