SVG不能正确渲染作为主干视图

SVG不能正确渲染作为主干视图

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

问题描述

我使用d3.js渲染地图SVG的世界(使用https://github.com/johan/world.geo.json/blob/master/countries.geo.json对于功能)。我封装呈现逻辑中的骨干视图。当我渲染视图,并将其附加到DOM,没有什么会显示在我的浏览器,虽然SVG标记正确生成看着生成的HTML时。当Backbone.View内没有封装这使得罚款。下面是使用Backbone.view我的code:

  / **
 * SVG地图视图
 * /
VAR的MapView = Backbone.View.extend({
    标签名:'SVG',
    translationOffset:[480,500]
    个zoomLevel:1000,    / **
     *设置地图投影仪和SVG路径生成
     * /
    初始化:功能(){
        this.projector = d3.geo.mercator();
        this.path = d3.geo.path()投影(this.projector)。
        this.projector.translate(this.translationOffset);
        this.projector.scale(this.zoomLevel);
    },    / **
     *渲染使用所提供的功能集合地图
     * /
    渲染:功能(){
        d3.select(this.el)
          .selectAll(路径)
          。数据(this.options.featureCollection.features)
          。进入()。追加(路径)
          .attr('D',this.path);
    },    / **
     *更新缩放级别
     * /
    变焦:功能(水平){
        this.projector.scale(this.zoomLevel =水平);
    },    / **
     *更新翻译偏移
     * /
    潘:功能(X,Y){
        this.projector.translate([
            this.translationOffset [0] + = X,
            this.translationOffset [1] + = Y
        ]);
    },    / **
     *刷新地图
     * /
    刷新:功能(){
        d3.select(this.el)
          .selectAll(路径)
          .attr('D',this.path);
    }
});VAR地图=新的图形页面({featureCollection:countryFeatureCollection});
。图$ el.appendTo('身体');
map.render();

这里的code这样的作品,而无需使用Backbone.View

  VAR投影机= d3.geo.mercator()
    PATH = d3.geo.path()。投影(投影机),
    国家= d3.select(身体)。追加(SVG),
    当zoomLevel = = 1000;COORDS = [480,500];
projector.translate(COORDS);
projector.scale(个zoomLevel);countries.selectAll(路径)
         。数据(countryFeatureCollection.features)
         。进入()。追加(路径)
         .attr('D',路径);

我还附上生成的SVG标记的屏幕截图。任何想法可能是错误怎么回事?

编辑 - 下面是最终解决这个,每个请求覆盖化妆方法:

  / **
 *需要为骨干不支持创建自定义化妆法
 *命名空间的HTML元素。
 * /
令:功能(记名,属性,内容){
    VAR EL =与Document.createElementNS('http://www.w3.org/2000/svg',标签名);
    如果(属性)$(EL).attr(属性);
    如果(内容)$(EL)的.html(内容);
    返回埃尔;
}


解决方案

的问题是,SVG元素需要一个命名空间。 D3做这行自动将您的;当你追加一个SVG的元素,它采用了命名空间http://www.w3.org/2000/svg。有关详细信息,请参阅。骨干,不幸的是,似乎并不支持命名空间的元素。你想改变方法。然后,你需要一个namespaceURI属性上的视图,设置适当的名称空间,或者只是做自动为SVG元素与HTML5分析器的一致性。

在任何情况下,你的问题的简单解决办法是包装在一个DIV元素的SVG,然后用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不能正确渲染作为主干视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 07:31