2012-12-12 8 views
12

डी 3 के अवशोषण अभी भी मेरे दिमाग को झुकाते हैं, इसलिए उम्मीद है कि मैं इसे सही तरीके से पेश कर रहा हूं।किसी दिए गए तत्व के लिए सक्रिय (चल रहे) D3 v3 संक्रमण को प्राप्त करने का मानक तरीका क्या है?

डी 3 में संस्करण 3, एक तत्व (जैसे कि एक चक्र) को देखते हुए और given only one transition possibly running per element क्या, सबसे अच्छा तरीका निर्धारित करने के लिए क्या उस तत्व पर वर्तमान चल रहा है संक्रमण है अगर वहाँ एक बिल्कुल है?

मुझे पता है कि मैं तत्व पर __transition__ का मैन्युअल रूप से निरीक्षण कर सकता हूं (हालांकि सहायता भी स्वागत है), लेकिन मैं वास्तव में थोड़ा उच्च स्तर की उम्मीद कर रहा हूं।

मेरा बड़ा लक्ष्य उप-संक्रमण बनाने के लिए है यदि केवल उप-संक्रमण में कोई संक्रमण हो। अन्यथा, मैं एक नया संक्रमण बनाउंगा।

+0

क्या आप निर्दिष्ट कर सकते हैं कि आप v2 या v3 के बारे में बात कर रहे हैं? – Wex

+0

मैंने संस्करण 3 कहा, लेकिन शायद मुझे इसे बोल्ड करना चाहिए या कुछ .. – Chuck

+0

निरीक्षण करना \ _transition_ शायद यह करने का सबसे प्रभावी तरीका है। एक तत्व समाप्त होने पर संक्रमण के बाद \ _transition_ गुण हटा दिया जाता है, इसलिए, आप यह देखने के लिए बस एक जांच कर सकते हैं कि \ _transition_ प्रॉपर्टी मौजूद है या नहीं। यदि ऐसा है, तो आप जानते हैं कि उस तत्व पर एक संक्रमण हो रहा है, और आप अधिक विस्तृत जानकारी प्राप्त करने के लिए \ _transition_ जांच सकते हैं। आपके पास संक्रमण तत्व के उप-तत्वों को हथियाने के विकल्प भी हैं, जैसे transition.selectAll() का उपयोग करना। आप transition.each() –

उत्तर

2

संक्षिप्त उत्तर यह है कि संक्रमण पाने के लिए कोई मानक तरीका नहीं है और आप ऐसा करने के लिए नहीं हैं। जैसा कि, यह समर्थित नहीं है।

थोड़ा लंबा जवाब यह है कि आपके उद्देश्यों के लिए, आप शायद __transition__ का उपयोग करके इसे हैक कर सकते हैं। विचार यह जांचना है कि __transition__ मौजूद है और यदि ऐसा है, तब तक प्रतीक्षा करें जब तक कि यह नया (उप) संक्रमण शुरू करने से पहले न हो।

कि ऐसा करने के लिए, यह एक उचित समारोह के साथ चयन प्रोटोटाइप का विस्तार करने में मदद करता है:

d3.selection.prototype.getTransition = function() { 
    if(this[0][0].__transition__) { 
    return this[0][0].__transition__[1]; 
    } else return undefined; 
} 

ध्यान दें कि यह यहाँ अत्यंत hacky और केवल काम है, अगर वहाँ में ठीक एक तत्व चयनके साथ बिल्कुल एक संक्रमण। हालांकि आपको विचार मिलना चाहिए।

अब, हम इस फ़ंक्शन का उपयोग यह निर्धारित करने के लिए कर सकते हैं कि कोई संक्रमण चल रहा है या नहीं।

if(sel.getTransition() !== undefined) { 
    // transition is there 
} else { 
    // no transition 
} 

दुर्भाग्य से, __transition__ आप संक्रमण वस्तु फिर से संगठित करने की अनुमति नहीं है, यानि कि निम्नलिखित काम नहीं करेगा।

sel.getTransition().transition()... 

तो एक subtransition वर्तमान में चल रहे एक के बाद शुरू होता है अनुकरण करने के लिए कर रहा है पूरा, कुछ चल रहा है कि क्या जांच करने के लिए और जैसे ही कुछ भी नहीं है के रूप में, अपने नए संक्रमण शुरू setTimeout का उपयोग करें:

function check() { 
    if(sel.getTransition() !== undefined) { 
    setTimeout(check, 100); 
    } else { 
    sel.transition().duration(1000)...; 
    } 
} 
check(); 

आप संक्रमण के बेहतर प्रभाव को बनाने के लिए चेक (100 एमएमएस) के बीच अंतराल को कम कर सकता है जो तुरंत पिछले एक का पालन करता है।

पूर्ण उदाहरण here। ध्यान दें कि लगभग सभी मामलों में, कहीं भी संक्रमण ऑब्जेक्ट का संदर्भ रखने और इसका उपयोग करने के लिए यह कहीं अधिक आसान और बेहतर है। यह उदाहरण वास्तव में केवल अवधारणा के एक हैकी सबूत के रूप में कार्य करता है।

+1

दिलचस्प समस्या का उपयोग कर संक्रमण में प्रत्येक तत्व को श्रोताओं को भी जोड़ सकते हैं। वर्तमान संक्रमण समाप्त होने पर सटीक गणना करने के लिए आप '__transition __ [1]' ऑब्जेक्ट के गुणों का उपयोग करके थोड़ा और अधिक कुशल बना सकते हैं, और तदनुसार अपना टाइमआउट सेट करें: http://jsfiddle.net/7SQBe/1/ – AmeliaBR

3

ऐसा करने का एक और तरीका: प्रत्येक नोड पर अपनी खुद की संपत्ति बनाएं जो वास्तविक d3.transition ऑब्जेक्ट्स की एक सरणी संग्रहीत करती है। एक नया संक्रमण बनाते समय, सरणी से अंतिम संक्रमण को पकड़ें और उप-संक्रमण बनाएं।

जटिलता यह है कि आपका नया संक्रमण सक्रिय संक्रमण के समान चयन पर आधारित नहीं हो सकता है।इसलिए, मैं .each() कॉल के भीतर प्रति-तत्व आधार पर नया "सुरक्षित" संक्रमण बना देता हूं।

function saveTransition(t) { 
    //save the transition immediately (don't wait for "start") 
    //clear it on "end" 
    t.each(function() { 
     var tArr = this.__tObj__ 
     if (!tArr) tArr = this.__tObj__ = []; 

     tArr.push(t); 
     //console.log("saving ", t, " for ",this); 
     }) 
    .each("end", function() { 
     var test = this.__tObj__.shift(); 
     // console.log("clearing ", t, " from " ,this, 
     //   (test == t ? "correctly" : "ERROR")); 
     }); 
} 
function newSafeTransition(node) { 
    var tArr = node.__tObj__; 
    if (tArr && tArr.length) { 

     var t = tArr[ tArr.length - 1 ]; 
     return t.filter(function(){ return this === node; }) 
       .transition().call(saveTransition); 
    } 
    else { 
     return d3.select(node).transition().call(saveTransition); 
    } 
} 

d3.selectAll("div.foo") 
    .transition().duration(3000) 
    .call(saveTransition) 
    .style("left", "100px"); 

d3.selectAll("div.bar") 
    .transition().duration(3000) 
    .call(saveTransition) 
    .style("top", "100px"); 

setTimeout(function() { 
    console.log("blue"); 

    d3.selectAll("div.blue") 
     .each(function() { 
      newSafeTransition(this).style("color", "blue"); 
     }); 
}, 1000); 

setTimeout(function() { 
    console.log("reposition"); 

    d3.selectAll("div.foo") 
     .each(function() { 
      newSafeTransition(this).style("left", "0px"); 
     }); 
}, 2000); 

http://jsfiddle.net/7SQBe/3/

यह शायद साफ किया जा सकता है, तो आप भी selection.transition() और transition.transition() तरीकों से अधिक से लिखने स्वचालित रूप से ऐसा करने के लिए कर सकता है। हालांकि, आप शायद यह इंगित करने के लिए एक तरीका रखना चाहते हैं कि क्या आप किसी भी निर्धारित संक्रमण के बाद नए संक्रमण को कतारबद्ध करना चाहते हैं या आप बाधित करना चाहते हैं।

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