0

更新:截至 2014 年 2 月,Meteor 支持响应式 SVG,因此无需解决方法。

流星 0.5.9

我想创建一组形状,集合中的每个文档一个。我可以在模板中一次创建一个形状,但不能在 {{#each 循环}} 内。

这有效:

<Template name="map">
  <svg viewBox="0 0 500 600" version="1.1">
    <rect x="0" y="0" width="100" height="100" fill={{color}}/>
  </svg>
</Template>

Template.map.color = function() {
  return "green";
};

这不会:

<Template name="map">
  <svg viewBox="0 0 500 600" version="1.1">
    {{#each colors}}
      <rect x="0" y="0" width="100" height="100" fill={{color}}/>
    {{/each}}
  </svg>
</Template>

Template.map.colors = function() {
  return [{color: "red"}, {color: "blue"}];
}

我尝试使用 {{#each}} 创建的任何内容都不会显示,即使我可以手动创建它们,即使 Meteor 通过模板插入的属性也是如此。

我还尝试将单个对象 {color: "red"} 发送到模板并使用 {{#with colors}},但这也不起作用。除了 SVG,我还在模板中添加了 plain s 以确保信息正确地到达模板,并且这些都按预期工作,使用 {{#each}} 和 {{#with}}。

我应该能够做我想做的事吗?

4

3 回答 3

3

(2013 年 4 月 1 日更新)

找到了一种将 Handlebars 与 Javascript 插入相结合的方法。必须感谢这个博客条目才能弄清楚这一点:http: //nocircleno.com/blog/svg-and-handlebars-js-templates/

我创建了以下两个文件,将它们放在新 Meteor 目录的客户端文件夹中,我成功获得了 html。

测试.js:

<head>
  <title>testing</title>
</head>

<body>
</body>

<template name="map">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    {{#each colors}}
      <rect x="0" y="{{yPosition}}" width="100" height="100" fill="{{color}}"/>
    {{/each}}
  </svg>
</template>

测试.html:

(function () {

  var count = 0;

  Template.map.yPosition = function() {
    count++;
    return (count-1) * 100;
  };  

  Template.map.colors = function() {
    return [{color: "red"}, {color: "blue"}];
  };

  Meteor.startup(function() {
    var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svgElement.width = 500;
    svgElement.height = 600;
    document.getElementsByTagName("body")[0].appendChild(svgElement);
    var svgFragment = new DOMParser().parseFromString(Template.map(), "text/xml");
    svgElement.appendChild(svgFragment.documentElement);
  }); 

})();
于 2013-03-31T14:47:24.313 回答
2

我在尝试使用 Meteor 和 SVG 元素时遇到了同样的问题,发现您可以添加元素并使用以下两种方法让它们显示出来。一种选择是将每个循环中的元素包装在 an 中<svg></svg>,如下所示:

<svg viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
{{#each pieces}}
  <svg xmlns="http://www.w3.org/2000/svg"><circle cx="{{x}}" cy="{{y}}" r="1" fill="{{color}}"></circle></svg>
{{/each}}
</svg>

另一个选项是(在模板渲染上)使用 jQuery 创建一个包含要插入的元素的 svg 元素,然后使用 jQuery 抓取该内部元素并将其插入到 DOM 中已经存在的 svg 元素中,就像这样(在咖啡脚本中) :

for piece in Pieces.find().fetch()
  $el = $("<svg><circle cx='#{piece.x}' cy='#{piece.y}' r='1' class='a'></circle></svg>")
  $el.find('circle').appendTo @$('svg')

您还可以使用 d3 或 RaphaelJS 之类的东西来进行插入。您甚至可以通过在 Collection 观察者回调中使用像 d3 这样的库来使各个元素对您的 Collection 产生反应并轻松地制作动画,就像这样(再次,coffeescript):

Pieces.find().observe {

  added: (piece)=>
    # using jquery (could use d3 instead)
    $el =  $("<svg><circle cx='#{piece.x}' cy='#{piece.y}' r='1' fill='#{piece.color}' data-id='#{piece._id}'></circle></svg>")
    $el.find('circle').appendTo @$('svg')

  changed: (newPiece, oldPiece)=>
    # using d3 to animate change
    d3.select("[data-id=#{oldPiece._id}]").transition().duration(1000).attr {
      cx: newPiece.x
      cy: newPiece.y
      fill: newPiece.color
    }

  removed: (piece)=>
    @$("[data-id=#{piece._id}]").remove()
}

这些方法似乎适用于 Mac 上最新的 Chrome、Safari、Firefox 浏览器,但我还没有在其他浏览器中测试过。

于 2013-05-11T21:49:18.740 回答
1

根据使用 Blaze页面,当 Blaze 发布时,Meteor 将拥有一流的 SVG 支持。

于 2014-03-13T13:02:58.880 回答