gpt4 book ai didi

svg - 如何根据数据创建 SVG 形状?

转载 作者:行者123 更新时间:2023-12-02 07:01:01 26 4
gpt4 key购买 nike

我有数据和形状定义的结构:

var data = [
{
"id": "first",
"shapes": [
{
"shape": "polygon",
"points": [["8","64"],["8","356"],["98","356"],["98","64"]]
}
]
},
{
"id": "second",
"shapes": [
{
"shape": "ellipse",
"cx": "63", "cy": "306", "rx": "27","ry": "18"
}, {
"shape": "polygon",
"points": [["174","262"],["171","252"],["167","262"]]
}
]
}
]; // in the data may be stored any SVG shape

我想创建 SVG:

<svg width="218" height="400">
<g transform="translate(0,400) scale(1,-1)">
<g>
<polygon points="8,64 8,356 98,356 98,64"/>
</g>
<g>
<ellipse cx="63" cy="306" rx="27" ry="18"/>
<polygon points="174,262 171,252 167,262"/>
</g>
</g>
</svg>

对于每个 data我要附加的元素 <g> :

var groups = svg.selectAll("g").data(data, function (d) {
return d.id;
});
groups.enter().append("g");

现在我正在为组形状绑定(bind)数据:

var shapes = groups.selectAll(".shape").data(function (d) {
return d.shapes;
}, function(d,i){return [d.shape,i].join('-');});

到目前为止,一切都符合预期。现在我想为每个进入的 DOM 节点分配具有适当形状的绘图函数,但显然 shapes.enter().each()在此上下文中不起作用(未定义)。我想它在每个 DOM 节点上工作,而不是在每个要绑定(bind)的数据上工作。这是有效的:

shapes.enter().append("g").each(function(draw, i) {
var shape = draw.shape;
d3.select(this).call(drawer[shape]);
});

但痛苦的副作用是 SVG 有两个级别 <g> :

<svg width="218" height="400">
<g transform="translate(0,400) scale(1,-1)">
<g>
<g>
<polygon points="8,64 8,356 98,356 98,64"/>
</g>
</g>
...
</svg>

如何摆脱它?如何正确构建基于数据的形状?

最佳答案

基于 AmeliaBR 提供的数据添加基本形状的两种方法都可以,但略微超出了 d3.js API。经过长时间的考虑,我决定添加回答我自己的问题。

寻找其他解决方案的灵感来自 Lars Kotthoff 的评论,该评论建议使用路径而不是原始 SVG 形状。在这种方法中,而不是添加第二级 <g>应该添加<path> :

shapes.enter().append("path").attr("d", function(d) {
return drawer[d.shape](d);
});

原创 drawer生成基本形状的对象将返回属性值 d<path> .

    var drawer = {
polygon: function (d) {
return [
"M", d.points[0].join(','),
"L", d.points
.slice(1, d.points.length)
.map(function (e) {
return e.join(",")
}), "Z"].join(" ");
},
ellipse: function (d) {
return [
'M', [d.cx, d.cy].join(','),
'm', [-d.rx, 0].join(','),
'a', [d.rx, d.ry].join(','),
0, "1,0", [2 * d.rx, 0].join(','),
'a', [d.rx, d.ry].join(','),
0, "1,0", [-2 * d.rx, 0].join(',')].join(' ');
},
circle: function (d) {
return this.ellipse({
cx: d.cx,
cy: d.cy,
rx: d.r,
ry: d.r
});
},
rect: function (d) {
return this.polygon({
points: [
[d.x, d.y],
[d.x + d.width, d.y],
[d.x + d.width, d.y + d.height],
[d.x, d.y + d.height]
]
});
},
path: function (d) {
return d.d;
}
};

您可以在 http://fiddle.jshell.net/daKkJ/4/ 查看工作示例

关于svg - 如何根据数据创建 SVG 形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20753636/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com