首页 > 解决方案 > 直观地对 svg 元素进行排序

问题描述

我在订购 SVG 元素时遇到了麻烦。我编写了一个脚本,它将数组中每个数字的比率与其中数字的总和相结合,并针对这些数字创建一个饼图。现在,我正在尝试添加一些动画,但本质上,当我尝试扩大切片的大小时,它似乎在以下路径后面。

我试过 add 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>

标签: javascriptcsssvgcharts

解决方案


不幸的是,正如您所注意到的,SVG 不支持z-index. 这个功能被提出并最终被拒绝。标签使用<svg>单个渲染/堆叠上下文,并在较早的孩子之上绘制后来的孩子。

以下是一些解决方法:

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

    document.getElementById("dd").childNodes.forEach((path) =>
      path.addEventListener('mouseenter', (e) =>
        path.parentNode.appendChild(path)
      )
    );
    
  2. 更改您的过渡动画,使它们不会导致重叠。执行此操作的自然方法是手动设置.style.transitionOrigin元素的 ,以便它们从条形图的中心缩放。请参阅变换原点。这将需要一些计算,但鉴于您已经在计算所有坐标,它应该不会太难。

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

顺便说一句,如果您不组装 HTML 字符串和 set innerHTML,而是使用document.createElement创建元素然后document.getElementById("dd").appendChild将这些元素添加为子元素,那么您的代码会更容易以这些方式使用。


推荐阅读