可视化排序 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 上下文,并在较早的子项之上绘制较晚的子项。
这里有一些解决方法:
使用 JavaScript 动态重新排序项目。您可以添加一个 mouseenter
事件处理程序,将元素移动到堆栈的末尾:
document.getElementById("dd").childNodes.forEach((path) =>
path.addEventListener('mouseenter', (e) =>
path.parentNode.appendChild(path)
)
);
改变你的过渡动画,这样它们就不会造成重叠。执行此操作的自然方法是手动设置元素的 .style.transitionOrigin
,以便它们从条形图的中心开始缩放。参见 transform-origin。这将需要一些计算,但鉴于您已经计算了所有坐标,应该不会太难。
创建单独的 <svg>
对象。然后你可以使用 z-index
,我相信。但是我认为相对于彼此定位它们是相当困难的。
顺便说一句,如果您没有 assemble 一个 HTML 字符串并设置 innerHTML
,而是使用 document.createElement
创建元素,然后 document.getElementById("dd").appendChild
添加这些元素作为子元素。
我在订购 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 上下文,并在较早的子项之上绘制较晚的子项。
这里有一些解决方法:
使用 JavaScript 动态重新排序项目。您可以添加一个
mouseenter
事件处理程序,将元素移动到堆栈的末尾:document.getElementById("dd").childNodes.forEach((path) => path.addEventListener('mouseenter', (e) => path.parentNode.appendChild(path) ) );
改变你的过渡动画,这样它们就不会造成重叠。执行此操作的自然方法是手动设置元素的
.style.transitionOrigin
,以便它们从条形图的中心开始缩放。参见 transform-origin。这将需要一些计算,但鉴于您已经计算了所有坐标,应该不会太难。创建单独的
<svg>
对象。然后你可以使用z-index
,我相信。但是我认为相对于彼此定位它们是相当困难的。
顺便说一句,如果您没有 assemble 一个 HTML 字符串并设置 innerHTML
,而是使用 document.createElement
创建元素,然后 document.getElementById("dd").appendChild
添加这些元素作为子元素。