如何解决如何删除树中的单个孩子?
给定以下树:
{
"name": "svg","type": "element","value": "","attributes": {
"xmlns": "http://www.w3.org/2000/svg","width": "1440","height": "1080"
},"children": [{
"name": "g","attributes": {},"children": [{
"name": "g","children": [{
"name": "g","attributes": {
"fill": "#627580"
},"children": [{
"name": "g","attributes": {
"stroke-linejoin": "round"
},"children": [{
"name": "path","attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},"children": []
},{
"name": "path","children": []
}]
},{
"name": "g","children": []
}]
}]
}]
}]
}]
}
...这是此 HTML 的表示:
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</g>
</svg>
如何在 JavaScript 中递归地转换此数据结构,以便折叠所有只有一个子项 <g>
的组 <g>
,并将其子项分配给其父项?
预期结果如下:
{
"name": "svg","attributes": {
"stroke-linejoin": "round"
},"children": [{
"name": "path","attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},"children": []
},{
"name": "path","children": []
}]
},{
"name": "g","children": []
}]
}]
}]
}
...这是此 HTML 的表示:
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</svg>
理想情况下,不应有一个 <g>
元素与单个子元素 <g>
一起存在。换句话说:
<g>
<g>
...
</g>
</g>
将转化为
<g>
...
</g>
这是我的尝试:
const collapseGroups = node => {
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
collapseGroups(child)
})
if (node.name == 'g' &&
node.children.length == 1 &&
node.children[0].name == 'g') {
node.children = node.children[0].children;
}
}
}
注意:我输入的是一个SVG文件,已经自动解析为上面提到的JS对象了。
解决方法
您可以在每个节点上使用递归函数。如果它检测到它是“g”类型,并且只有一个孩子,那么节点吸收孩子,同时合并attributes属性:
function simplify(node) {
return node.name === 'g' && node.children.length === 1
&& node.children[0].name === 'g'
? {
...simplify(node.children[0]),attributes: { // Merge attributes of the two nodes that merge into one
...node.attributes,...node.children[0].attributes
}
}
: {
...node,children: node.children.map(simplify)
};
}
// Sample input:
let root = {
"name": "svg","type": "element","value": "","attributes": {
"xmlns": "http://www.w3.org/2000/svg","width": "1440","height": "1080"
},"children": [{
"name": "g","attributes": {},"children": [{
"name": "g","children": [{
"name": "g","attributes": {
"fill": "#627580"
},"children": [{
"name": "g","attributes": {
"stroke-linejoin": "round"
},"children": [{
"name": "path","attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},"children": []
},{
"name": "path","children": []
}]
},{
"name": "g","children": []
}]
}]
}]
}]
}]
};
root = simplify(root);
console.log(root);
您可以运行结构的基本遍历,但是,如果您遇到具有单个 g
标记子级的 g
标记,只需对该子级调用 merge
:>
var d = {'name': 'svg','type': 'element','value': '','attributes': {'xmlns': 'http://www.w3.org/2000/svg','width': '1440','height': '1080'},'children': [{'name': 'g','attributes': {},'attributes': {'fill': '#627580'},'attributes': {'stroke-linejoin': 'round'},'children': [{'name': 'path','attributes': {'d': 'M150 0 L75 200 L225 200 Z'},'children': []},{'name': 'path','children': []}]},{'name': 'g','children': []}]}]}]}]}]}
function merge(d){
if (d.name != 'g' || d.children.length > 1 || d.children[0].name != 'g'){
return {...d,'children':d.children.map(merge)}
}
return merge(d.children[0])
}
console.log(merge(d))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。