2012-03-10 12 views
19

मैं sv3 में दुनिया का नक्शा प्रस्तुत करने के लिए d3.js का उपयोग कर रहा हूं (सुविधाओं के लिए https://github.com/johan/world.geo.json/blob/master/countries.geo.json का उपयोग कर)। मैं बैकबोन व्यू में प्रतिपादन तर्क को समाहित कर रहा हूं। जब मैं दृश्य प्रस्तुत करता हूं और इसे डीओएम से जोड़ता हूं, तो मेरे ब्राउज़र में कुछ भी प्रदर्शित नहीं होता है, हालांकि जेनरेट किए गए HTML को देखते समय एसवीजी मार्कअप सही ढंग से उत्पन्न होता है। यह बैकबोन के भीतर encapsulating जब ठीक है प्रस्तुत करता है। देखें। यहाँ मेरी कोड 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); 

का उपयोग कर मैं भी उत्पन्न एसवीजी मार्कअप का एक स्क्रीनशॉट संलग्न किया है बिना। कोई विचार क्या गलत हो सकता है?

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

उत्तर

26

मुद्दा यह है कि "svg" तत्व एक नाम स्थान की आवश्यकता है: -

enter image description here

संपादित करें यहाँ ओवरराइड कर विधि है कि इस को हल करने, अनुरोध के अनुसार समाप्त हो गया है। डी 3 यह आपके लिए स्वचालित रूप से करता है; जब आप एक "svg" तत्व जोड़ते हैं, तो यह नामस्थान "http://www.w3.org/2000/svg" का उपयोग करता है। विवरण के लिए, src/core/ns.js देखें। दुर्भाग्य से, बैकबोन नामित तत्वों का समर्थन नहीं करता है। आप view.make विधि को बदलना चाहते हैं। फिर आपको उपयुक्त नामस्थान सेट करने के लिए अपने दृश्य पर नेमस्पेसुरि संपत्ति की आवश्यकता होगी, या केवल HTML5 पार्सर के साथ स्थिरता के लिए इसे स्वचालित रूप से एसवीजी तत्वों के लिए करें।

किसी भी दर पर, आपकी समस्या के लिए एक सरल फिक्स एक डीवी तत्व में अपने एसवीजी को लपेटना है, और फिर एसवीजी तत्व बनाने के लिए डी 3 का उपयोग करना है।

+0

धन्यवाद से! मैंने अपने दृश्य में 'मेक' ओवरराइड किया और createElementNS को 'http://www.w3.org/2000/svg' के साथ createElement के बजाय इस्तेमाल किया और ऐसा लगता है कि यह चाल है। मार्गदर्शन की सराहना करें। –

+1

@rr: क्या आप अपनी मेक विधि कहीं कहीं पोस्ट कर सकते हैं? –

+0

@PierreSpring: हो गया, यह सुनिश्चित नहीं है कि यह बैकबोन के नए संस्करणों के साथ कितना प्रासंगिक है, मैं नहीं रख रहा हूं। –

4

आप बस इनिशियलाइज़ समारोह में देखने के तत्व सेट कर सकते हैं इस प्रकार है:

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] 
     ); 
    } 
); 

यह explicite होने का लाभ है।

+1

यह रीढ़ की हड्डी के लेखकों द्वारा यहां उल्लेख किया गया है: https://github.com/documentcloud/backbone/pull/1357 –

+1

हालांकि आपको एक div बनाने की आवश्यकता नहीं है, 'setElement (दस्तावेज़। createElementNS ('http://www.w3.org/2000/svg','svg')) 'ठीक है। –

3

चेक इस बाहर 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); 
    } 
} 
}); 
संबंधित मुद्दे