可视化排序 svg 元素

Ordering the svg elements visually

我在订购 SVG 元素时遇到了问题。我编写了一个脚本,该脚本采用数组中每个数字与其中数字总和的比率,并根据这些数字创建一个饼图。现在,我正在尝试添加一些动画,但本质上,当我尝试放大切片的大小时,它似乎落后于以下路径。

我试过添加 z-index,但显然 属性 不适用于 SVG 元素。我尝试过使用 3D 变换,但我了解到它在 SVG 上也不起作用。我该如何克服这个问题?

我的代码:

var radius = 100
        var slices = [3,4,3]
        var sumSlices = slices.reduce((last,num) => last + num)
        var degrees = Array.from(slices, num => (360*num)/sumSlices)
        var colorPalet = ["#e668a0", "#53e1a0", "#53a7e1", "#f8a1c8", "#95f2c7", "#94caf0"]
        var pie
        var obj = new Array
        var t, f1, f2, g1, g2
        t = 0
        degrees.forEach((degree, i) => {

            obj[i] = new Object
            
            f1 = radius * Math.cos((Math.PI/180)*t)
            g1 = -(radius * Math.sin((Math.PI/180) * t))
            
            obj[i]["lGo"] = f1 + " " + g1
            t = degree + t
            f2 = (radius * Math.cos((Math.PI/180) * t)) - f1
            g2 = -(g1 + (radius * Math.sin((Math.PI/180) * t)))
            if(degree < 180) obj[i]["aGo"] = radius + " " + radius + " 0 0 0" + f2 + " " + g2
            else obj[i]["aGo"] = radius + " " + radius + " 0 1 0" + f2 + " " + g2
            
        })

        var tags = new Array
        obj.forEach((sl, i) => {
            
            tags[i] = '<path d="M'+ radius + " " + radius +' l'+ sl["lGo"] +' a'+ sl["aGo"] +' Z" fill="'+ colorPalet[i] +'" />'
        })

        document.getElementById("dd").innerHTML = tags.reduce((a, b) => a + " " + b)
        
        body {margin:0}

        .con {
            position: absolute;
            top:50%;
            left:50%
        }

        .conIn {
            position: absolute;
            transform: translate(-50%, -50%);
        }

        svg {
            overflow: initial;
        }

        path {
            transition: 1s;
            position: relative;
            z-index: 1;
            transform-origin: center
        }

        path:hover {
            transform:scale(1.4);
            
        }
    <div class="con">
        <div class="conIn">
            <svg id="dd" width="100" height="100" >
               
            </svg>
        </div>
    </div>

很遗憾,如您所见,SVG 不支持 z-index。此功能 proposed 并最终被拒绝。 <svg> 标签使用单个 rendering/stacking 上下文,并在较早的子项之上绘制较晚的子项。

这里有一些解决方法:

  1. 使用 JavaScript 动态重新排序项目。您可以添加一个 mouseenter 事件处理程序,将元素移动到堆栈的末尾:

    document.getElementById("dd").childNodes.forEach((path) =>
      path.addEventListener('mouseenter', (e) =>
        path.parentNode.appendChild(path)
      )
    );
    
  2. 改变你的过渡动画,这样它们就不会造成重叠。执行此操作的自然方法是手动设置元素的 .style.transitionOrigin,以便它们从条形图的中心开始缩放。参见 transform-origin。这将需要一些计算,但鉴于您已经计算了所有坐标,应该不会太难。

  3. 创建单独的 <svg> 对象。然后你可以使用 z-index,我相信。但是我认为相对于彼此定位它们是相当困难的。

顺便说一句,如果您没有 assemble 一个 HTML 字符串并设置 innerHTML,而是使用 document.createElement 创建元素,然后 document.getElementById("dd").appendChild 添加这些元素作为子元素。