制作可重用 svg 实体所需的 d3 结构是什么

What is the d3 structure needed to make a reusable svg entity

我正在使用 API 描述,从 DITA (XML) 转换为 JSON 在 d3 中创建铁路图。我只想定义各种元素一次(如下面代码中的 sidingLsidingR)。我有 siding 风格。在我的全局变量声明中,我有 sidingL(和 sidingR 的变体):

var sidingL = d3.svg.path()
    .attr("d", "M50,0 v80 a10,10 0 0  10,10 h20")
    .attr("class", "siding");

然后,在添加 SVG canvas (svgContainer) 之后,我添加:

    var L = svgContainer.append(sidingL);
    var R = svgContainer.append(sidingR);

我希望能实例化每个 sidingLsidingR

的实例

我已经为这个实验精简了我的大部分代码,以实现每个侧板之一的 SVG canvas 上的可见渲染。在 Firefox Web Developer Toolkit、控制台或调试视图中没有任何内容呈现并且看不到任何有用的信息!

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Railroad siding</title>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <link 
href='http://fonts.googleapis.com/css?family=Lato&subset=latin,latin-ext'
 rel='stylesheet' type='text/css'>
    <style>
  .siding {
    fill: none;
    stroke: black;
    stroke-width: 6px;
    stroke-linecap: round;
    stroke-linejoin: round;

  }
  </style>
</head>
<body>
<script type="text/javascript">

  //set up constants
  var canvasWidth= 4000;
  var canvasHeight=800

  var sidingL = d3.svg.path()
    .attr("d", "M50,0 v80 a10,10 0 0  10,10 h20")
    .attr("class", "siding");

  var sidingR = d3.svg.path()
    .attr("d", "M100,0 v80 a10,10 0 1 10,10 h-20")
    .attr("class", "siding");

  // Get the data
  var data;
  d3.json("APIsyntax.json", function(error, json) {
  //if (error) return console.warn(error);
   // Canvas
  var svgContainer = d3.select("body")
    .append("svg")
    .attr("width", canvasWidth)
    .attr("height", canvasHeight);

  // tryout for option siding path
  var L = svgContainer.append(sidingL);
  var R = svgContainer.append(sidingR);


  });      
    </script>
</body>
</html> 

有几种方法可以做到(因此,这个问题是 "too broad")。但是,按照您在代码中所做的方式,这就是问题所在:

var L = svgContainer.append(sidingL);

您正试图在其中附加一个 d3.svg.path(),但这是行不通的。您可以做的是使用变量来创建元素,然后将它们附加为函数的返回值:

var L = svgContainer.append(function(){ return sidingL});

这是一个小片段:

var canvasWidth= 200;
var canvasHeight=200;

var sidingL = document.createElementNS("http://www.w3.org/2000/svg", "path");
sidingL.setAttribute("d", "M50,0 v80 a10,10 0 0  10,10 h20");
sidingL.setAttribute("class", "siding");

var sidingR = document.createElementNS("http://www.w3.org/2000/svg", "path");
sidingR.setAttribute("d", "M100,0 v80 a10,10 0 1 10,10 h-20");
sidingR.setAttribute("class", "siding");

var svgContainer = d3.select("body")
    .append("svg")
    .attr("width", canvasWidth)
    .attr("height", canvasHeight);

var L = svgContainer.append(function(){ return sidingL});
var R = svgContainer.append(function(){ return sidingR});
.siding {
    fill: none;
    stroke: black;
    stroke-width: 6px;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

D3方式

我不知道 "reusable" 是不是你的意思,但是 D3 方式 执行上述代码的方式要短得多:

var paths = ["M50,0 v80 a10,10 0 0  10,10 h20",
 "M100,0 v80 a10,10 0 1 10,10 h-20"];
  
var svg = d3.select("body")
 .append("svg")
  .attr("width", 300)
  .attr("height", 300);
  
var myPaths = svg.selectAll("path")
 .data(paths)
  .enter()
  .append("path")
  .attr("class", "siding");
  
myPaths.attr("d", function(d){ return d});
.siding {
    fill: none;
    stroke: black;
    stroke-width: 6px;
    stroke-linecap: round;
    stroke-linejoin: round;
  };
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

我们只是将 paths 存储在一个变量中(在本例中为 var paths)并将它们用作路径的 data