【问题标题】:Using Meteor to create SVG in template works, but not in #each loop使用 Meteor 在模板中创建 SVG 工作,但不是在 #each 循环中
【发布时间】:2013-03-15 18:12:10
【问题描述】:

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

流星 0.5.9

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

这行得通:

<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}}。

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

【问题讨论】:

    标签: svg meteor each handlebars.js


    【解决方案1】:

    (2013 年 4 月 1 日更新)

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

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

    Testing.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>
    

    Testing.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);
      }); 
    
    })();
    

    【讨论】:

    • 我没有得到相同的结果。元素已成功创建,但它们不可见。在对此进行大量研究之后,我非常确信问题是在创建 SVG 画布后您无法添加 SVG 元素,因为它们位于不同的命名空间中。我已经成功地将它们添加到 javascript 中,但没有添加到像这样的车把模板中。
    • 哎呀!你是对的,我只是假设没有显示任何内容,因为我的服务器没有设置为提供 SVG(顺便说一句,这是刷新我的 SVG 知识的好方法)。查看我的更新答案
    【解决方案2】:

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

    <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 浏览器,但我还没有在其他浏览器中测试过。

    【讨论】:

    • 我不会想到将每个单独的元素包装在自己的 svg 标签中。这使创建的元素数量增加了一倍,但它确实有效!
    • 现在 Meteor 的一个分支支持 SVG!它还不是正式版本的一部分,但您可以执行meteor update --release blaze-rc0,您的 SVG 元素将像任何其他 html 模板元素一样更新。更多信息:github.com/meteor/meteor/wiki/Using-Blaze
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 2013-05-22
      • 1970-01-01
      • 2013-09-17
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多