【问题标题】:SVG not rendering properly as a backbone viewSVG 无法正确渲染为主干视图
【发布时间】:2012-03-27 21:56:00
【问题描述】:

我正在使用 d3.js 以 svg 呈现世界地图(使用 https://github.com/johan/world.geo.json/blob/master/countries.geo.json 表示功能)。我将渲染逻辑封装在主干视图中。当我渲染视图并将其附加到 DOM 时,我的浏览器中没有显示任何内容,尽管在查看生成的 HTML 时正确生成了 SVG 标记。当不封装在 Backbone.View 中时,这可以很好地呈现。这是我使用 Backbone.view 的代码:

/**
 * SVG Map view
 */
var MapView = Backbone.View.extend({
    tagName: 'svg',
    translationOffset: [480, 500],
    zoomLevel: 1000,

    /**
     * Sets up the map projector and svg path generator
     */
    initialize: function() {
        this.projector = d3.geo.mercator();
        this.path = d3.geo.path().projection(this.projector);
        this.projector.translate(this.translationOffset);
        this.projector.scale(this.zoomLevel);
    },

    /**
     * Renders the map using the supplied features collection
     */
    render: function() {
        d3.select(this.el)
          .selectAll('path')
          .data(this.options.featureCollection.features)
          .enter().append('path')
          .attr('d', this.path);
    },

    /**
     * Updates the zoom level
     */
    zoom: function(level) {
        this.projector.scale(this.zoomLevel = level);
    },

    /**
     * Updates the translation offset
     */
    pan: function(x, y) {
        this.projector.translate([
            this.translationOffset[0] += x,
            this.translationOffset[1] += y
        ]);
    },

    /**
     * Refreshes the map
     */
    refresh: function() {
        d3.select(this.el)
          .selectAll('path')
          .attr('d', this.path);
    }
});

var map = new MapView({featureCollection: countryFeatureCollection});
map.$el.appendTo('body');
map.render();

这是不使用 Backbone.View 的代码

var projector = d3.geo.mercator(),
    path = d3.geo.path().projection(projector),
    countries = d3.select('body').append('svg'),
    zoomLevel = 1000;

coords = [480, 500];
projector.translate(coords);
projector.scale(zoomLevel);

countries.selectAll('path')
         .data(countryFeatureCollection.features)
         .enter().append('path')
         .attr('d', path);

我还附上了生成的 SVG 标记的屏幕截图。知道这里可能出了什么问题吗?

编辑 - 这是根据请求最终解决此问题的覆盖 make 方法:

/**
 * Custom make method needed as backbone does not support creation of
 * namespaced HTML elements.
 */
make: function(tagName, attributes, content) {
    var el = document.createElementNS('http://www.w3.org/2000/svg', tagName);
    if (attributes) $(el).attr(attributes);
    if (content) $(el).html(content);
    return el;
}

【问题讨论】:

  • 鉴于 make 方法已被删除,现在做这件事的正确方法是什么?

标签: javascript html svg backbone.js d3.js


【解决方案1】:

看看这个http://jsfiddle.net/nocircleno/QsEp2/ 来自http://nocircleno.com/blog/svg-with-backbone-js/

Backbone.View.extend({
  nameSpace: "http://www.w3.org/2000/svg",
  _ensureElement: function() {
     if (!this.el) {
        var attrs = _.extend({}, _.result(this, 'attributes'));
        if (this.id) attrs.id = _.result(this, 'id');
        if (this.className) attrs['class'] = _.result(this, 'className');
        var $el = $(window.document.createElementNS(_.result(this, 'nameSpace'), _.result(this, 'tagName'))).attr(attrs);
        this.setElement($el, false);
     } else {
        this.setElement(_.result(this, 'el'), false);
     }
 }
});

【讨论】:

    【解决方案2】:

    您可以简单地在初始化函数中设置视图的元素,如下所示:

    Backbone.View.extend({
        // This is only for informaiton. The node will
        // be raplaced in the initialize function.
        tagName: 'svg',
    
        initialize: function () {
            this.setElement(
                d3.select($('<div/>')[0]).append('svg')[0]
            );
        }
    );
    

    这具有明确的优点。

    【讨论】:

    【解决方案3】:

    问题在于“svg”元素需要命名空间。 D3 会自动为您执行此操作;当您附加“svg”元素时,它使用命名空间“http://www.w3.org/2000/svg”。详情请见src/core/ns.js。不幸的是,Backbone 似乎不支持命名空间元素。您想更改 view.make 方法。然后你需要在你的视图上设置一个 namespaceURI 属性来设置适当的命名空间,或者只是为 SVG 元素自动设置以与 HTML5 解析器保持一致。

    无论如何,解决问题的一个简单方法是将 SVG 包装在 DIV 元素中,然后使用 D3 创建 SVG 元素。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-24
    • 2012-06-16
    • 1970-01-01
    • 2021-02-10
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多