我在我的项目中使用 svg 圆圈,
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
<g>
<g id="one">
<circle fill="green" cx="100" cy="105" r="20" />
</g>
<g id="two">
<circle fill="orange" cx="100" cy="95" r="20" />
</g>
</g>
</svg>
我使用 g
标记中的 z-index 来首先显示元素。在我的项目中,我只需要使用 z-index 值,但我不能将 z-index 用于我的 svg 元素。我用谷歌搜索了很多,但我没有找到任何相对的东西。所以请帮助我在我的 svg 中使用 z-index。
这是DEMO.
规格
在 SVG 规范 1.1 版中,渲染顺序基于文档顺序:
first element -> "painted" first
3.3 渲染顺序 SVG 文档片段中的元素具有隐式的绘制顺序,SVG 文档片段中的第一个元素首先被“绘制”。随后的元素被绘制在先前绘制的元素之上。
解决方案(更清洁更快)
您应该将绿色圆圈作为要绘制的最新对象。所以交换这两个元素。
这里是您的 jsFiddle 的分支。
解决方案(替代)
带有属性 xlink:href
的标签 use
(对于 SVG 2 只有 href
)和元素的 id 作为值。请记住,即使结果看起来不错,这也可能不是最佳解决方案。有一点时间,这里是规范 SVG 1.1 "use" Element 的链接。
目的:避免要求作者修改引用的文档以将 ID 添加到根元素。
SVG 2 的注意事项
SVG 2 Specification 是下一个主要版本,仍支持上述功能。
3.4.渲染顺序 SVG 中的元素位于三个维度中。除了它们在 SVG 视口的 x 和 y 轴上的位置之外,SVG 元素也位于 z 轴上。 z 轴上的位置定义了它们的绘制顺序。沿着 z 轴,元素被分组到堆叠上下文中。 3.4.1。在 SVG 中建立堆叠上下文...堆叠上下文是概念性工具,用于描述在呈现文档时元素必须一个在另一个之上绘制的顺序,...
SVG 2 支持 Mozilla - 绘画
我如何知道我的浏览器是否支持 svg 2.0
我可以使用 SVG
不推荐使用的 XLink 命名空间 对于 SVG 2,使用 href 而不是额外的不推荐使用的命名空间 xlink:href(感谢 G07cha)
正如其他人所说,z-index 由元素在 DOM 中出现的顺序定义。如果手动重新排序您的 html 不是一个选项或者会很困难,您可以使用 D3 重新排序 SVG 组/对象。
使用 D3 更新 DOM 顺序和模拟 Z-Index 功能
Updating SVG Element Z-Index With D3
在最基本的级别(如果您没有将 ID 用于其他任何事情),您可以使用元素 ID 作为 z-index 的替代品并使用它们重新排序。除此之外,您几乎可以尽情发挥想象力。
代码片段中的示例
var circles = d3.selectAll('circle') var label = d3.select('svg').append('text') .attr('transform', 'translate(' + [5,100] + ')') var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }) , yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }), 半径: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } var setOrderBy = 'IDs'; var setOrder = d3.descending;标签.text(setOrderBy); circles.data(zOrders[setOrderBy]) circles.sort(setOrder);
基本思想是:
使用 D3 选择 SVG DOM 元素。 var circles = d3.selectAll('circle') 创建一些 z 索引数组,与您的 SVG 元素(要重新排序)具有 1:1 的关系。以下示例中使用的 Z 索引数组是 ID、x 和 y 位置、半径等...... var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }), yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; } ), radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } 然后,使用 D3 绑定你的 z -该选择的索引。 circles.data(zOrders[setOrderBy]);最后,调用 D3.sort 根据数据对 DOM 中的元素重新排序。 circles.sort(setOrder);
例子
https://i.stack.imgur.com/aFllN.png
您可以按 ID 堆叠
https://i.stack.imgur.com/dNKrO.png
最左边的 SVG 在顶部
https://i.stack.imgur.com/3Cx9M.png
顶部最小半径
https://i.stack.imgur.com/ZGGDr.png
或指定一个数组以将 z-index 应用于特定排序——在我的示例代码中,数组 [3,4,1,2,5] 将第 3 个圆圈(按原始 HTML 顺序)移动/重新排序为第 1 个DOM,第 4 为第 2,第 1 为第 3,依此类推...
尝试反转 #one
和 #two
。看看这个小提琴:http://jsfiddle.net/hu2pk/3/
Update
在 SVG 中,z-index 由元素在文档中出现的顺序定义。如果需要,您也可以查看此页面:https://stackoverflow.com/a/482147/1932751
d3.selection.prototype.moveToFront = function() { return this.each(function() { this.parentNode.appendChild(this); }); };
然后您可以通过 stackoverflow.com/questions/14167863/… 说 selection.moveToFront()
您可以使用 use。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
<g>
<g id="one">
<circle fill="green" cx="100" cy="105" r="20" />
</g>
<g id="two">
<circle fill="orange" cx="100" cy="95" r="20" />
</g>
</g>
<use xlink:href="#one" />
</svg>
绿色圆圈出现在顶部。
jsFiddle
#one
被绘制了两次。但如果你愿意,你可以通过 CSS 隐藏第一个实例。 use
与克隆引用的 DOM 元素具有相同的效果
<g>
本身的顺序。
xlink:href
已被弃用,取而代之的是 href
。
使用 D3:
如果要按顺序重新插入每个选定元素,作为其父元素的最后一个子元素。
selection.raise()
selection.raise()
在 D3 v4 中是新的。
正如所讨论的,svgs 按顺序呈现并且不考虑 z-index(目前)。也许只是将特定元素发送到其父元素的底部,以便它最后渲染。
function bringToTop(targetElement){
// put the element at the bottom of its parent
let parent = targetElement.parentNode;
parent.appendChild(targetElement);
}
// then just pass through the element you wish to bring to the top
bringToTop(document.getElementById("one"));
为我工作。
更新
如果您有一个包含组的嵌套 SVG,则需要将项目从其父节点中取出。
function bringToTopofSVG(targetElement){
let parent = targetElement.ownerSVGElement;
parent.appendChild(targetElement);
}
SVG 的一个很好的特性是每个元素都包含它的位置,而不管它嵌套在哪个组中:+1:
使用 D3:
如果要将元素以相反的顺序添加到数据中,请使用:
.insert('g', ":first-child")
而不是 .append('g')
Adding an element to top of a group element
svgs 没有 z-index。但是 svg 通过它们在 DOM 中的位置来确定哪些元素是最上面的。因此,您可以删除对象并将其放置在 svg 的末尾,使其成为“最后渲染”的元素。然后将那个在视觉上呈现为“最顶层”。
使用 jQuery:
function moveUp(thisObject){
thisObject.appendTo(thisObject.parents('svg>g'));
}
用法:
moveUp($('#myTopElement'));
使用 D3.js:
d3.selection.prototype.moveUp = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
用法:
myTopElement.moveUp();
截至本答案发布之日,干净、快速、简单的解决方案并不令人满意。它们是建立在 SVG 文档缺乏 z 顺序的有缺陷的陈述之上的。库也不是必需的。一行代码可以执行大多数操作来操纵在 xyz 空间中移动 2D 对象的应用程序开发中可能需要的对象或对象组的 z 顺序。
SVG 文档片段中肯定存在 Z 顺序
所谓的 SVG 文档片段是从基本节点类型 SVGElement 派生的元素树。 SVG 文档片段的根节点是一个 SVGSVGElement,它对应于 HTML5
像在 CSS 中那样在 SVGElement 上具有 z-index 属性会破坏 SVG 渲染模型。 W3C SVG Recommendation v1.1 2nd Edition 的第 3.3 和 3.4 节指出 SVG 文档片段(来自 SVGSVGElement 的后代树)是使用所谓的树的深度优先搜索来呈现的。该方案在任何意义上都是按顺序排列的。
Z 顺序实际上是一种计算机视觉捷径,可以避免需要真正的 3D 渲染以及光线追踪的复杂性和计算需求。 SVG 文档片段中元素的隐式 z-index 的线性方程。
z-index = z-index_of_svg_tag + depth_first_tree_index / tree_node_qty
这很重要,因为如果您想将低于正方形的圆圈移动到其上方,您只需将正方形插入圆圈之前。这可以在 JavaScript 中轻松完成。
支持方法
SVGElement 实例有两种方法支持简单易用的 z 顺序操作。
parent.removeChild(子)
parent.insertBefore(孩子,childRef)
不会造成混乱的正确答案
因为 SVGGElement(
parent.insertBefore(parent.removeChild(gRobot), gDoorway)
如果作为 SVGGElement gRobot 的子级绘制的机器人层位于作为 SVGGElement gDoorway 的子级绘制的门口之前,则机器人现在位于门口之后,因为门口的 z 顺序现在是机器人的 z 顺序的 1。
上移命令几乎同样简单。
parent.insertBefore(parent.removeChild(gRobot), gDoorway.nextSibling())
只要想想 a=a 和 b=b 就可以记住这一点。
insert after = move above
insert before = move below
让 DOM 处于与视图一致的状态
这个答案正确的原因是因为它是最小且完整的,并且像 Adobe 产品或其他设计良好的图形编辑器的内部一样,使内部表示处于与渲染创建的视图一致的状态。
另类但有限的方法
另一种常用的方法是将 CSS z-index 与多个 SVG 文档片段(SVG 标签)结合使用,除了底部一个之外,所有的背景都大多是透明的。再一次,这破坏了 SVG 渲染模型的优雅,使得在 z 顺序中向上或向下移动对象变得困难。
笔记:
(https://www.w3.org/TR/SVG/render.html v 1.1,第 2 版,2011 年 8 月 16 日) 3.3 渲染顺序 SVG 文档片段中的元素具有隐式绘制顺序,SVG 中的第一个元素文档片段首先被“绘制”。随后的元素被绘制在先前绘制的元素之上。 3.4 如何呈现组 分组元素,例如'g' 元素(参见容器元素)具有生成一个临时独立画布的效果,该画布初始化为透明黑色,在其上绘制子元素。组完成后,将应用为组指定的任何滤镜效果以创建修改后的临时画布。修改后的临时画布被合成到背景中,同时考虑到组上的任何组级蒙版和不透明度设置。
我们已经 2019 并且 z-index
在 SVG 中仍然不受支持。
您可以在网站 SVG2 support in Mozilla 上看到 z-index
的状态 – 未实现。
您还可以在 Bug 360148 "Support the 'z-index' property on SVG elements" 网站上查看(报告:12 年前)。
但是你在 SVG 中有 3 种可能性来设置它:
使用 element.appendChild(aChild);使用 parentNode.insertBefore(newNode, referenceNode);使用 targetElement.insertAdjacentElement(positionStr, newElement); (在 IE 中不支持 SVG)
交互式演示示例
拥有这 3 个功能。
变量状态 = 0,索引 = 100; document.onclick = function(e) { if(e.target.getAttribute('class') == 'clickable') { var parent = e.target.parentNode; if(state == 0) parent.appendChild(e.target); else if(state == 1) parent.insertBefore(e.target, null); //null - 将它添加到末尾 else if(state == 2) parent.insertAdjacentElement('beforeend', e.target);否则 e.target.style.zIndex = index++; } }; if(!document.querySelector('svg').insertAdjacentElement) { var label = document.querySelectorAll('label')[2]; label.setAttribute('disabled','disabled'); label.style.color = '#aaa'; label.style.background = '#eee'; label.style.cursor = '不允许'; label.title = '您的浏览器不支持此功能。'; } label{background:#cef;padding:5px;cursor:pointer} .clickable{cursor:pointer} With:
这是有关 z-index 和 SVG 搜索的最高 Google 结果。在阅读了所有答案后,其中一些非常好,我仍然感到困惑。
所以对于像我这样的新手来说,这是目前的总结,9 年后的 2022 年。
您不能将 z-index 与 SVG 一起使用。
在 SVG 中,z-index 由元素在文档中出现的顺序定义。
如果您希望某些东西出现在顶部,或者更靠近用户,请在最后绘制或在之前插入。 Source
SVG 2 可以支持 z-index 但可能永远不会出现
SVG 2 是实现该功能和其他功能的提议,但它有永远不会向前发展的风险。
SVG 2 于 2016 年进入候选推荐阶段,并于 2018 年进行了修订,最新草案于 2021 年 6 月 8 日发布。Source
然而,它没有很多支持,很少有人在研究它。 Source 所以不要屏住呼吸等待这个。
您可以使用 D3,但可能不应该
D3 一个常用的数据可视化方法通过绑定 z-index 然后排序来支持 z-index,但它是一个庞大而复杂的库,如果您只是希望某个 SVG 出现在堆。
将 SVG 元素推到最后,使其 z-index 位于顶部。在 SVG 中,没有称为 z-index 的属性。尝试下面的 javascript 将元素置于顶部。
var Target = document.getElementById(event.currentTarget.id);
var svg = document.getElementById("SVGEditor");
svg.insertBefore(Target, svg.lastChild.nextSibling);
目标:是我们需要将其置于顶部的元素 svg:是元素的容器
通过变换移动到前面:TranslateZ
警告:仅适用于 FireFox
我最终使用的 use 的一个更好的例子。
<svg>
<defs>
<circle id="one" fill="green" cx="40" cy="40" r="20" />
<circle id="two" fill="orange" cx="50" cy="40" r="20"/>
</defs>
<use href="#two" />
<use href="#one" />
</svg>
要控制顺序,您可以更改这些 use
元素的 href
属性值。这对动画很有用。
由于 defs
,圆形元素只绘制一次。
很容易做到:
克隆你的项目 对克隆的项目进行排序 用克隆替换项目
函数rebuildElementsOrder(选择器,orderAttr,sortFnCallback){让$items = $(选择器);让 $clone = $items.clone(); $cloned.sort(sortFnCallback != null ? sortFnCallback : function(a,b) { let i0 = a.getAttribute(orderAttr)?parseInt(a.getAttribute(orderAttr)):0, i1 = b.getAttribute(orderAttr)? parseInt(b.getAttribute(orderAttr)):0; 返回 i0 > i1?1:-1; }); $items.each(function(i, e){ e.replaceWith($cloned[i]); }) } $('use[order]').click(function() { rebuildElementsOrder('use[order]' , 'order'); /* 你可以使用 z-index 属性进行内联 css 声明 ** getComputedStyle 总是在内部和外部 CSS decl [在 chrome 中测试]rebuildElementsOrder('use[order]', null,函数(a, b) { 让 i0 = a.style.zIndex?parseInt(a.style.zIndex):0, i1 = b.style.zIndex?parseInt(b.style.zIndex):0; 返回 i0 > i1 ?1:-1; }); */ });使用[订单] { 光标:指针; }
不定期副业成功案例分享
xlink:href
已被弃用,取而代之的是href
。