2012-06-18 15 views
12

मैं एक रीढ़ की हड्डी के दृश्य में डी 3 का उपयोग कर एक ग्राफ visuzalization पर काम कर रहा हूँ। मैं उपयोगकर्ता को ग्राफ को चुटकी-ज़ूम करने की अनुमति देता हूं, वेबकिट ट्रांसफॉर्म का उपयोग करके आसानी से संक्रमण कर रहा हूं, और रिलीज पर फिर से चल रहा हूं। कोड को सरल रखने के लिए, मैं तत्वों के लिए नई स्थिति और आकारों का पुनर्मूल्यांकन करने के बजाय, नए पैमाने पर ग्राफ को फिर से तैयार कर रहा हूं (यह मेरा मूल दृष्टिकोण था, लेकिन मेरी टीम ने रेड्रा रूट का अनुरोध किया था)।डीओएम नोड क्लीनअप डी 3 में कैसे काम करता है?

[मैंने ट्विटर के माध्यम से Bostock के साथ बात की। यह वास्तव में चीजों को करने का पसंदीदा तरीका नहीं है]

जो चीज़ मैं देख रहा हूं वह यह है कि प्रत्येक रेड्रा के लिए, मैं बहुत से डोम नोड्स को डंप कर रहा हूं जो साफ़ नहीं होते हैं।

यह ईवेंट हैंडलर/क्लोजर के भीतर परिपत्र संदर्भ से संबंधित नहीं है, क्योंकि मैंने अपने लेबल के अलावा सभी को अक्षम कर दिया है (इन्हें कोई हैंडलर संलग्न नहीं है), और वही व्यवहार होता है।

मैंने ग्राफ से तत्वों को आक्रामक रूप से हटाने का प्रयास किया है, लेकिन डोम नोड्स अभी भी रिसाव लगते हैं।

यहां कुछ प्रासंगिक कोड है। 'रेंडर' लेबल के एक नए सेट के लिए बुलाया जाता है। ज़ूमिंग परिष्करण पर, 'करीब' पुराने ग्राफ पर कहा जाता है, और एक नया एक और दृश्य इन्स्टेन्शियशन के साथ बनाया जाता है और 'प्रस्तुत करना' करने के लिए कॉल:

render: function() { 

     // create the svg offscreen/off dom 
     //document.createElementNS(d3.ns.prefix.svg, "svg") 
     var svg = this.svg = d3.select(this.el) 
      .append("svg:svg") 
      .attr('width', this.VIEW_WIDTH) 
      .attr('height', this.VIEW_HEIGHT) 

     this._drawTimeTicks.call(this, true); 
     return this; 
    }, 



_drawTimeTicks: function(includeLabels) { 
    var bounds = this.getDayBounds(); 
    var min = bounds.start; 
    var date = new Date(min); 
    var hour = 1000 * 60 * 60; 
    var hourDiff = 60 * this.SCALE; 
    var graphX = (date.getTime() - min)/1000/60; 
    var textMargin = 7; 
    var textVert = 11; 

    // Using for loop to draw multiple vertical lines 
    // and time labels. 

    var timeTicks = d3.select(this.el).select('svg'); 
    var width = timeTicks.attr('width'); 
    var height = timeTicks.attr('height'); 

    for (graphX; graphX < width; graphX += hourDiff) { 
     timeTicks.append("svg:line") 
      .attr("x1", graphX) 
      .attr("y1", 0) 
      .attr("x2", graphX) 
      .attr("y2", height) 
      .classed('timeTick'); 

     if (includeLabels) { 
      timeTicks.append("svg:text") 
       .classed("timeLabel", true) 
       .text(this.formatDate(date)) 
       .attr("x", graphX + textMargin) 
       .attr("y", textVert); 
     } 

     date.setTime(date.getTime() + hour); 
    } 



close: function() { 
     console.log("### closing the header"); 
     this.svg.selectAll('*').remove(); 
     this.svg.remove(); 
     this.svg = null; 
     this.el.innerHTML = ''; 

     this.unbind(); 
     this.remove(); 
    } 

आप देखते हैं, मैं कुछ भी मुश्किल नहीं कर रहा हूँ कर सकते हैं घटना हैंडलर या बंद के साथ। कुछ ज़ूम इंटरैक्शन के साथ मैं दर्जनों डोम नोड्स को रिसाव कर सकता हूं जिन्हें कभी भी जीसी द्वारा पुनः दावा नहीं किया जाता है।

क्या यह एक स्मृति रिसाव है, या डी 3 भविष्य के ग्राफ निर्माण/अपडेट को अनुकूलित करने के लिए दृश्यों के पीछे कुछ कर रहा है? क्या ऐसे ग्राफ को नष्ट करने का कोई बेहतर तरीका है जिसे मैं नहीं जानता हूं?

कोई भी विचार?

उत्तर

20

डी 3 आपके नोड्स में कोई छुपा संदर्भ नहीं रखता है, इसलिए "डोम नोड क्लीनअप" की कोई आंतरिक अवधारणा नहीं है। केवल चयन हैं, जो डोम तत्वों के सरणी हैं, और डोम स्वयं ही हैं। यदि आप डीओएम से कोई तत्व हटाते हैं, और आप इसके लिए कोई अतिरिक्त संदर्भ नहीं रखते हैं, तो इसे कचरा कलेक्टर द्वारा पुनः दावा किया जाना चाहिए।

(इसके अलावा: यह स्पष्ट नहीं है कि आप जिस रिसाव का जिक्र कर रहे हैं वह डीओएम या अनाथ तत्वों में शेष तत्व है जो कचरा कलेक्टर द्वारा पुनः दावा नहीं किया जा रहा है। अतीत में, कुछ पुराने ब्राउज़रों में बम कचरा इकट्ठा होता था जो डोम के बीच परिपत्र संदर्भ एकत्र करता था तत्व और जावास्क्रिप्ट बंद हो जाता है, लेकिन मुझे ऐसे किसी भी मुद्दे से अवगत नहीं है जो आधुनिक ब्राउज़रों को प्रभावित करता है।)

यदि आप डोम अपडेट कर रहे हैं, तो ऐसा करने का सबसे अधिक प्रदर्शन करने वाला तरीका (आमतौर पर) डेटा-जॉइन का उपयोग कर रहा है, क्योंकि यह आपको मौजूदा तत्वों का पुन: उपयोग करने की अनुमति देता है और केवल उन गुणों को संशोधित करता है जिन्हें बदलने की आवश्यकता है। डेटा-जॉइन के लिए एक महत्वपूर्ण फ़ंक्शन का उपयोग करना object constancy के लिए भी एक अच्छा विचार है; यदि एक ही डेटा अद्यतन से पहले और बाद में प्रदर्शित होता है, तो आपको इसके सभी विशेषताओं को पुन: सम्मिलित करने की आवश्यकता नहीं हो सकती है, और ब्राउजर अपडेट करने के लिए कम काम करता है।

कुछ मामलों में, वहाँ इस तरह के एक संलग्न जी तत्व की विशेषता को बदलने को अद्यतन करने के बजाय वंशज तत्वों की स्थिति को अद्यतन करने के रूप में तेजी से कर रहे हैं मनमाने ढंग से अद्यतन, के लिए विकल्प हैं। एक और उदाहरण के रूप में, आप व्यूबॉक्स विशेषता को बदलकर बस एक एसवीजी तत्व के भीतर ज्यामितीय ज़ूमिंग कर सकते हैं। लेकिन ज्यामितीय ज़ूमिंग एक बहुत ही सीमित मामला है; सामान्य रूप से, सबसे कुशल अद्यतन इस बात पर निर्भर करता है कि वास्तव में क्या बदल रहा है। डेटा-जॉइन का उपयोग करें ताकि आप उन तत्वों की संख्या को कम कर सकें जिन्हें आप जोड़ते हैं या हटाते हैं, और उन गुणों की संख्या को कम करें जिन्हें आपको पुनः संयोजित करने की आवश्यकता है।

एक जोड़े को अन्य बातों के मैं बाहर बिंदु होगा ...

  • आप एक नहीं बल्कि पाश के लिए एक का उपयोग करने से एक ही समय में एक से अधिक टिक बनाने के लिए, डेटा में शामिल होने के इस्तेमाल कर सकते हैं। लूप के लिए लगभग डी 3 के साथ कभी भी उपयोग नहीं किया जाता है क्योंकि डेटा-जॉइन लूप के बिना कई तत्व (और पदानुक्रमित संरचनाएं) बना सकता है। इससे भी बेहतर, एक समय प्रारूप (d3.time.format) के साथ धुरी घटक (d3.svg.axis) और एक समय पैमाने (d3.time.scale) का उपयोग करें।

  • डी 3 का हाल संस्करणों "svg:" की आवश्यकता नहीं है नाम स्थान है, तो आप "पाठ", "पंक्ति", आदि

  • मैं किसी भी स्थिति के बारे में सोच नहीं सकता है, जहां selectAll("*").remove() बनाता है जोड़ सकते हैं समझ। "*" चयनकर्ता सभी वंशजों से मेल खाता है, इसलिए यह प्रत्येक माता-पिता को अपने माता-पिता से हटा देगा। आपको बच्चों के तत्वों के अनावश्यक हटाने के बजाय हमेशा शीर्ष-सबसे तत्व-एसवीजी कंटेनर को हटाने का प्रयास करना चाहिए।

+0

धन्यवाद। मैं अलग-अलग ज़ूमिंग विकल्पों को देखूंगा, लेकिन कारण मैं पहले उनका उपयोग नहीं कर रहा था यह था कि मेरे ग्राफ में आयताकारों के भीतर स्थिर-फ़ॉन्ट-आकार का टेक्स्ट है, और मुझे ज़ूम इन/आउट पर किसी भी आवश्यक छंटनी को निर्धारित करने की आवश्यकता है। लेकिन फिर, सभी मदद के लिए धन्यवाद :) – Gopherkhan

+0

हाँ, ऐसे कई कारण हैं जिनसे ज्यामितीय ज़ूमिंग अपर्याप्त है। कभी-कभी आप उन मुद्दों को पैच कर सकते हैं, ज़ूम स्तर को बढ़ाने के दौरान फ़ॉन्ट आकार को कम करके कहें, लेकिन प्रायः तत्वों को व्यवस्थित रूप से स्थानांतरित करना आसान होता है। – mbostock

+0

मुझे पता है कि यह एक पुराना सवाल है, लेकिन डीओएम नोड क्लीनअप पर कुछ आईई-विशिष्ट नोट्स के लिए यहां देखें: http://stackoverflow.com/questions/18575452/why-do-my-svg-nodes-leak-memory-in -अर्थात – explunit

संबंधित मुद्दे