SVG 无法正确呈现为主干视图 [英] SVG not rendering properly as a backbone view

查看:17
本文介绍了SVG 无法正确呈现为主干视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 d3.js 在 svg 中渲染世界地图(使用 ".有关详细信息,请参阅 src/core/ns.js.不幸的是,Backbone 似乎不支持命名空间元素.您想更改 view.make 方法.然后,您需要在视图上使用 namespaceURI 属性来设置适当的命名空间,或者只是为 SVG 元素自动执行此操作以与 HTML5 解析器保持一致.

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

I'm using d3.js to render a map of the world in svg (using https://github.com/johan/world.geo.json/blob/master/countries.geo.json for the features). I am encapsulating the rendering logic in a Backbone View. When I render the view and attach it to the DOM, nothing displays in my browser, though the SVG markup is correctly generated when looking at the generated HTML. This renders fine when not encapsulating within a Backbone.View. Here's my code using 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();

Here's the code that works, without using 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);

I've also attached a screenshot of the generated SVG markup. Any idea what could be going wrong here?

Edit - Here's the overridden make method that ended up solving this, per request:

/**
 * 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;
}

解决方案

The issue is that the "svg" element requires a namespace. D3 does this for your automatically; when you append an "svg" element, it uses the namespace "http://www.w3.org/2000/svg". For details, see src/core/ns.js. Backbone, unfortunately, does not appear to support namespaced elements. You'd want to change the view.make method. Then you'd need a namespaceURI property on your view to set the appropriate namespace, or just do it automatically for SVG elements for consistency with the HTML5 parser.

At any rate, a simple fix for your problem is to wrap your SVG in a DIV element, and then use D3 to create the SVG element.

这篇关于SVG 无法正确呈现为主干视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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