如何基于数据创建SVG形状? [英] How to create SVG shapes based on data?

查看:126
本文介绍了如何基于数据创建SVG形状?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have structure with data and shapes definition:

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>

对于每个数据 < g>

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

现在我是组形状的数据绑定:

Now I'm binding data for group shapes:

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

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

So far it was as expected. Now I want to for each entering DOM node dispatch drawing function with proper shape but apparently shapes.enter().each() is not working in this context (not defined). I suppose it works rather on each DOM node than on each data to be bound. And this is working:

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

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

But painful side-effect is that SVG has two levels of <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>

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

How to get rid of that? How to build data based shapes correctly?

推荐答案

基于AmeliaBR提供的数据添加基本形状的两种方法是确定的, d3.js API。经过长时间的考虑,我决定添加回答我自己的问题。

Two ways to add basic shapes based on data provided by AmeliaBR are ok but slightly outside d3.js API. After long consideration I've decided to add answer my own question.

启发寻找其他解决方案是Lars Kotthoff的问题建议使用路径而不是原始的SVG形状的评论。在这种方法中,应当添加< path> :,而不是添加< g>

Inspiration for searching other solution was comment of Lars Kotthoff under question suggesting using paths instead of primitive SVG shapes. In this approach instead of adding second level of <g> there should be added <path>:

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

原始 drawer < path> 的属性 d 的值。

    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形状?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆