javascript - 直观地对 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>
解决方案
不幸的是,正如您所注意到的,SVG 不支持z-index
. 这个功能被提出并最终被拒绝。标签使用<svg>
单个渲染/堆叠上下文,并在较早的孩子之上绘制后来的孩子。
以下是一些解决方法:
使用 JavaScript 动态地重新排序项目。您可以添加一个
mouseenter
将元素移动到堆栈末尾的事件处理程序:document.getElementById("dd").childNodes.forEach((path) => path.addEventListener('mouseenter', (e) => path.parentNode.appendChild(path) ) );
更改您的过渡动画,使它们不会导致重叠。执行此操作的自然方法是手动设置
.style.transitionOrigin
元素的 ,以便它们从条形图的中心缩放。请参阅变换原点。这将需要一些计算,但鉴于您已经在计算所有坐标,它应该不会太难。创建单独的
<svg>
对象。然后你可以使用z-index
,我相信。但我认为,将它们相对于彼此定位将非常困难。
顺便说一句,如果您不组装 HTML 字符串和 set innerHTML
,而是使用document.createElement
创建元素然后document.getElementById("dd").appendChild
将这些元素添加为子元素,那么您的代码会更容易以这些方式使用。
推荐阅读
- php - 如何检查登录用户在 Laravel 5 的管理列上是否有“1”?
- c# - 异常不会从任务 (TPL) 中冒泡
- android - 如何在 Android 上将 Javascript 注入 GeckoView
- python - 在将列表移动到另一个函数之前将列表更改为元组在计算上是否更快?
- java - 为什么当我想从文本文件中删除字符串时它不起作用?
- python - 与for循环表单集断开连接后如何重新连接django信号
- c# - 当 ShowInTaskbar="False" 时检测窗口被 Win+D 最小化
- ruby - 在 eval 语句中面临“没有将 nil 隐式转换为字符串”错误
- json - 我怎样才能知道 Django 查询集的下一个值而不必循环和存储值?
- java - 我的程序停止打印到控制台,但继续在后台运行。没有抛出异常