কোনও রূপান্তর শেষে কলব্যাক চাওয়া


99

আমাকে D3.js ব্যবহার করে একটি ফেইডআউট পদ্ধতি (jQuery এর অনুরূপ) তৈরি করতে হবে । আমাকে যা করতে হবে তা হল 0 টি ব্যবহার করে অস্বচ্ছতা সেট করা transition()

d3.select("#myid").transition().style("opacity", "0");

সমস্যাটি হ'ল ট্রানজিশনটি কখন শেষ হয়েছে তা অনুধাবনের জন্য আমার একটি কলব্যাক দরকার। আমি কীভাবে কলব্যাক বাস্তবায়ন করতে পারি?

উত্তর:


145

আপনি রূপান্তরের "শেষ" ইভেন্টের জন্য শুনতে চান।

// d3 v5
d3.select("#myid").transition().style("opacity","0").on("end", myCallback);

// old way
d3.select("#myid").transition().style("opacity","0").each("end", myCallback);
  • এই ডেমোটি "ক্রম" ইভেন্টটি ব্যবহার করে অনেকগুলি ক্রম সংক্রমণের শৃঙ্খলাবদ্ধ করে।
  • ডোনাট উদাহরণ যে থেকে D3 সঙ্গে জাহাজ এই চেইন একসাথে একাধিক ট্রানজিশন ব্যবহার করে।
  • এখানে আমার নিজস্ব ডেমো যা সংক্রমণের শুরু এবং শেষের সময়ে উপাদানগুলির স্টাইলকে পরিবর্তন করে।

এর জন্য ডকুমেন্টেশন থেকে transition.each([type],listener):

যদি টাইপ নির্দিষ্ট করা থাকে, ট্রানজিশনের ইভেন্টগুলির জন্য শ্রোতা যুক্ত করে, "শুরু" এবং "শেষ" উভয় ইভেন্টকে সমর্থন করে। ক্রান্তিকালায় ধীরে ধীরে দেরি এবং সময়কাল থাকলেও শ্রোতাকে সংক্রমণের প্রতিটি পৃথক উপাদানের জন্য অনুরোধ করা হবে। প্রতিটি ইভেন্টের ক্রান্তিকালীন শুরু হওয়ার সাথে সাথে সূচনা ইভেন্টটি তাত্ক্ষণিক পরিবর্তন ট্রিগার করতে ব্যবহৃত হতে পারে। শেষ ইভেন্টটি বর্তমান উপাদানটি নির্বাচন করে thisএবং একটি নতুন ট্রানজিশন গ্রহণের মাধ্যমে বহু-পর্যায় রূপান্তর শুরু করতে ব্যবহার করা যেতে পারে । শেষ ইভেন্টের সময় তৈরি হওয়া কোনও রূপান্তর বর্তমান ট্রানজিশন আইডির উত্তরাধিকারী হবে এবং এর ফলে পূর্বনির্ধারিত একটি নতুন ট্রানজিশন ওভাররাইড করবে না।

দেখুন বিষয়ে এই ফোরামে থ্রেড আরো বিস্তারিত জানার জন্য।

সবশেষে, দ্রষ্টব্য যে আপনি যদি উপাদানগুলি ম্লান হয়ে যাওয়ার পরে কেবল সরিয়ে দিতে চান (ট্রানজিশন শেষ হওয়ার পরে), আপনি ব্যবহার করতে পারেন transition.remove()


7
আপনাকে অনেক ধন্যবাদ. এটি একটি দুর্দান্ত গ্রন্থাগার, তবে ডকুমেন্টেশনে গুরুত্বপূর্ণ তথ্য খুঁজে পাওয়া এত সহজ নয়।
টনি

9
সুতরাং, রূপান্তরের শেষ থেকে অব্যাহত রাখার এই পথে আমার সমস্যাটি হ'ল এটি আপনার ফাংশনটি এন বার চালায় (রূপান্তরকারী উপাদানগুলির সেটগুলিতে এন আইটেমগুলির জন্য)। এটি কখনও কখনও আদর্শ থেকে অনেক দূরে।
স্টিভেন লু

4
আমি একই সমস্যা আছে। শেষ সরিয়ে দেওয়ার পরে এটি একবারে ফাংশনটি চালিত করতে চাই
canyon289

4
একটি (সমস্ত উপাদান সমাপ্তির পরিবর্তে) এর জন্য সমস্ত ট্রানজিশন শেষ হওয়ার পরে আপনি কীভাবে কলব্যাক সম্পাদন করবেন d3.selectAll()? অন্য কথায়, আমি কেবলমাত্র সমস্ত ফাংশন রূপান্তর শেষ করে একটি ফাংশন কলব্যাক করতে চাই।
hobes3

হাই, স্ট্যাক / গ্রুপ বারের চার্টের প্রথম লিঙ্কটি একটি পর্যবেক্ষণযোগ্য নোটবুককে নির্দেশ করে যা কোনও .eachইভেন্ট শ্রোতা বা ইভেন্টটিকে ব্যবহার করে না "end"। এটি "চেইন" রূপান্তরগুলি বলে মনে হচ্ছে না। দ্বিতীয় লিঙ্কটি গিথুবকে নির্দেশ করে যা আমার জন্য লোড হয় না।
লাল মটর

66

একটি ছোট আপডেটের সাথে v3 এর জন্য মাইক বোস্টকের সমাধান :

  function endall(transition, callback) { 
    if (typeof callback !== "function") throw new Error("Wrong callback in endall");
    if (transition.size() === 0) { callback() }
    var n = 0; 
    transition 
        .each(function() { ++n; }) 
        .each("end", function() { if (!--n) callback.apply(this, arguments); }); 
  } 

  d3.selectAll("g").transition().call(endall, function() { console.log("all done") });

5
যদি নির্বাচনের শূন্য উপাদান থাকে তবে কলব্যাক কখনই চলবে না। if (transition.size() === 0) { callback(); }
এটির

4
যদি (! কলব্যাক) কলব্যাক = ফাংশন () {}; তাত্ক্ষণিকভাবে ফিরে না, বা একটি ব্যতিক্রম ছুঁড়ে না কেন? একটি অবৈধ কলব্যাক এই রুটিনের পুরো উদ্দেশ্যকে পরাভূত করে, কেন এটি অন্ধ প্রহরী তৈরির মতো করে চলে? :)
প্রিজমা

4
@ কেশেশান্ডার সহজেই কিছুই করতে পারে না, যেহেতু ব্যবহারকারী একই প্রভাব ফেলবে: (রূপান্তরের শেষে কোনও কলব্যাক কল নেই) function endall(transition, callback){ if(!callback) return; // ... } বা যেহেতু ব্যতিক্রমী কলটিব্যাক ছাড়াই এই ফাংশনটি কল করা সর্বাধিক সত্যই ত্রুটি পরিস্থিতি সামাল দেওয়ার উপযুক্ত উপায় function endall(transition, callback){ if(!callback) throw "Missing callback argument!"; // .. }
হোন

4
সুতরাং যখন আমরা পৃথক enter()এবং exit()স্থানান্তরগুলি পেয়েছি এবং তিনটি শেষ না হওয়া পর্যন্ত অপেক্ষা করতে চাই, আমাদের কলব্যাকে কোডটি লাগানো দরকার এটি তিনবার ডাকা হয়েছে তা নিশ্চিত করার জন্য? ডি 3 এত অগোছালো! আমি চাই আমি অন্য লাইব্রেরিটি বেছে নিই।
মাইকেল শ্যাপার 0

4
আমার যোগ করা উচিত, আমি বুঝতে পারি যে আপনার উত্তরটি আমি গ্রিপ করা কিছু সমস্যা সমাধান করে এবং এটি প্রয়োগ করতে আমি কোনও ইউটিলিটি ফাংশন লিখতে পারি। তবে আমি এটি প্রয়োগ করার মতো সুন্দর উপায় খুঁজে পাইনি এবং এখনও প্রতিটি সংক্রমণের জন্য অতিরিক্ত কাস্টমাইজেশনের অনুমতি দিই, বিশেষত যখন নতুন এবং পুরানো ডেটার জন্য ট্রানজিশন আলাদা হয়। আমি নিশ্চিত যে আমি কিছু নিয়ে আসব, তবে 'এই সমস্ত পরিবর্তনগুলি শেষ হয়ে গেলে' এই কলব্যাকটি প্রার্থনা করুন 'মনে হবে এমন একটি ব্যবহারের ক্ষেত্রে যা বাক্সের বাইরেই সমর্থিত হওয়া উচিত, ডি 3 এর মতো পরিপক্ক লাইব্রেরিতে। সুতরাং দেখে মনে হচ্ছে যে আমি ভুল লাইব্রেরিটি বেছে নিয়েছি really আসলেই ডি 3 এর দোষ নয়। যাইহোক, আপনার সাহায্যের জন্য ধন্যবাদ।
মাইকেল শ্যাপার

44

এখন, d3 v4.0 এ, স্পষ্টভাবে ইভেন্ট হ্যান্ডলারদের স্থানান্তরের সাথে সংযুক্ত করার জন্য একটি সুবিধা রয়েছে:

https://github.com/d3/d3-Transition#transition_on

কোনও রূপান্তর শেষ হয়ে গেলে কোড কার্যকর করতে, আপনার যা যা প্রয়োজন তা হ'ল:

d3.select("#myid").transition().style("opacity", "0").on("end", myCallback);

সুন্দর। ইভেন্ট হ্যান্ডলারগুলি স্থূল।
কেফংক

এছাড়াও রয়েছে transition.remove()( লিঙ্ক ), যা উপাদান থেকে উপাদানকে রূপান্তর করার সাধারণ ব্যবহারের ক্ষেত্রে পরিচালনা করে: `" প্রতিটি নির্বাচিত উপাদানটির জন্য, রূপান্তর শেষ হওয়ার পরে উপাদানটি সরিয়ে দেয়, যতক্ষণ না উপাদানটির অন্য কোনও সক্রিয় বা মুলতুবি ট্রানজিশন নেই If " উপাদানটির অন্যান্য সক্রিয় বা মুলতুবি ট্রানজিশন রয়েছে, কিছুই করে না ""
brichins

9
দেখে মনে হচ্ছে এটিকে পিইআর উপাদান বলা হয় যা রূপান্তরটি প্রয়োগ করা হয়, যা আমার বোঝার থেকে প্রশ্নটি নয় is
টেলর সি হোয়াইট

10

একটি সামান্য পৃথক পদ্ধতির যা এক সাথে চলমান অনেক উপাদানগুলির সাথে অনেকগুলি ট্রানজিশন থাকা অবস্থায়ও কাজ করে:

var transitions = 0;

d3.select("#myid").transition().style("opacity","0").each( "start", function() {
        transitions++;
    }).each( "end", function() {
        if( --transitions === 0 ) {
            callbackWhenAllIsDone();
        }
    });

ধন্যবাদ, এটি আমার পক্ষে সুন্দরভাবে কাজ করেছে। আমি একটি পৃথক বার চার্ট লোড করার পরে স্বয়ংক্রিয়ভাবে এক্স-অক্ষের লেবেল ওরিয়েন্টেশনটি কাস্টমাইজ করার চেষ্টা করছিলাম। কাস্টমাইজেশন লোড হওয়ার আগে কার্যকর করতে পারে না এবং এটি একটি ইভেন্ট হুক সরবরাহ করে যার মাধ্যমে আমি এটি করতে পারি।
হোয়াইটস্ট্রাইডার

6

মাইক বোস্টকের সমাধানের আরও একটি সংস্করণ নীচে দেওয়া হয়েছে এবং @ কাশেসান্ডারের উত্তরে @ হিউজেস মন্তব্য দ্বারা অনুপ্রাণিত হয়েছেন। এটি transitionশেষ হওয়ার পরে একক কলব্যাক করে ।

একটি dropফাংশন দেওয়া হয়েছে ...

function drop(n, args, callback) {
    for (var i = 0; i < args.length - n; ++i) args[i] = args[i + n];
    args.length = args.length - n;
    callback.apply(this, args);
}

... আমরা এর d3মতো প্রসারিত করতে পারি :

d3.transition.prototype.end = function(callback, delayIfEmpty) {
    var f = callback, 
        delay = delayIfEmpty,
        transition = this;

    drop(2, arguments, function() {
        var args = arguments;
        if (!transition.size() && (delay || delay === 0)) { // if empty
            d3.timer(function() {
                f.apply(transition, args);
                return true;
            }, typeof(delay) === "number" ? delay : 0);
        } else {                                            // else Mike Bostock's routine
            var n = 0; 
            transition.each(function() { ++n; }) 
                .each("end", function() { 
                    if (!--n) f.apply(transition, args); 
                });
        }
    });

    return transition;
}

জেএসফিডাল হিসাবে

ব্যবহার transition.end(callback[, delayIfEmpty[, arguments...]]):

transition.end(function() {
    console.log("all done");
});

... বা transitionempty চ্ছিক বিলম্বের সাথে খালি থাকলে:

transition.end(function() {
    console.log("all done");
}, 1000);

... বা alচ্ছিক callbackযুক্তি সহ:

transition.end(function(x) {
    console.log("all done " + x);
}, 1000, "with callback arguments");

d3.transition.endমিলিসেকেন্ডের সংখ্যা নির্দিষ্ট করা থাকলে বা দ্বিতীয় তর্কটি সত্যবাদী হলেcallback খালি দিয়েও পাস করা প্রয়োগ করা হবে । এটি কোনও অতিরিক্ত যুক্তি (এবং কেবলমাত্র সেই যুক্তিগুলি) কাছে ফরোয়ার্ড করবে । গুরুত্বপূর্ণভাবে, এটি ডিফল্টরূপে যদি খালি থাকে তবে এটি প্রয়োগ করবে না , এটি সম্ভবত এই ক্ষেত্রে একটি নিরাপদ অনুমান।transition callbackcallbacktransition


এটি দুর্দান্ত, আমি এটি পছন্দ করি।
কাশান্দ্র

4
ধন্যবাদ @ কেশেশান্ডার এটি সত্যই আপনার উত্তর দিয়ে অনুপ্রেরণা দিয়ে শুরু হয়েছিল!
মিলোস

সত্যিকার অর্থে ভাবেন না যে আমাদের একটি ড্রপ ফাংশন বা তর্কগুলি পাস করার প্রয়োজন, কারণ একই প্রভাবটি একটি মোড়ক ফাংশন বা বাঁধাই ব্যবহার করে অর্জন করা যেতে পারে। নাহলে আমি মনে করি এটি একটি দুর্দান্ত সমাধান +1
আহমেদ মাসুদ

একটি যাদুমন্ত্র মত কাজ করে !
বেনোত সৌভের

এই প্রতিক্রিয়া, .end () দেখুন এখন আনুষ্ঠানিকভাবে যোগ করেনি হয়েছে - stackoverflow.com/a/57796240/228369
chrismarx

5

D3 v5.8.0 + হিসাবে, এখন এটি ব্যবহার করার একটি সরকারী উপায় রয়েছে transition.end। দস্তাবেজগুলি এখানে রয়েছে:

https://github.com/d3/d3-Transition#transition_end

বোস্টকের একটি কার্যকারী উদাহরণ এখানে:

https://observablehq.com/@d3/transition-end

এবং মূল ধারণাটি হ'ল কেবল সংযোজন দ্বারা .end(), রূপান্তরটি এমন প্রতিশ্রুতি ফিরিয়ে দেবে যা সমস্ত উপাদানকে রূপান্তরিত না করা পর্যন্ত সমাধান হবে না:

 await d3.selectAll("circle").transition()
      .duration(1000)
      .ease(d3.easeBounce)
      .attr("fill", "yellow")
      .attr("cx", r)
    .end();

আরও জন্য সংস্করণ রিলিজ নোট দেখুন:

https://github.com/d3/d3/reLives/tag/v5.8.0


4
এটি জিনিস পরিচালনা করার খুব সুন্দর উপায়। আমি কেবল বলব, আপনারা যারা আমাকে পছন্দ করেন তাদের জন্য যারা v5- র সমস্ত কিছুই জানেন না এবং কেবল এটি প্রয়োগ করতে চান, আপনি <স্ক্রিপ্ট src = " d3js.org/d3-transition.v1 ব্যবহার করে নতুন রূপান্তর লাইব্রেরি আমদানি করতে পারেন .min.js "> </ স্ক্রিপ্ট >
DGill

0

কলব্যাক ফাংশনটিতে আর্গুমেন্টগুলি কাশ্যাস্যান্ডার দ্বারা মাইক বোস্টকের সমাধানটি উন্নত করেছে :

function d3_transition_endall(transition, callback, arguments) {
    if (!callback) callback = function(){};
    if (transition.size() === 0) {
        callback(arguments);
    }

    var n = 0;
    transition
        .each(function() {
            ++n;
        })
        .each("end", function() {
            if (!--n) callback.apply(this, arguments);
    });
}

function callback_function(arguments) {
        console.log("all done");
        console.log(arguments);
}

d3.selectAll("g").transition()
    .call(d3_transition_endall, callback_function, "some arguments");

-2

প্রকৃতপক্ষে টাইমার ব্যবহার করে এটি করার আরও একটি উপায় রয়েছে।

var timer = null,
    timerFunc = function () {
      doSomethingAfterTransitionEnds();
    };

transition
  .each("end", function() {
    clearTimeout(timer);
    timer = setTimeout(timerFunc, 100);
  });

-2

আমি একটি ভেরিয়েবল ব্যবহার করে ট্রানজিশনে সময়কাল নির্ধারণ করে একটি অনুরূপ সমস্যা সমাধান করেছি। তারপরে আমি setTimeout()পরের ফাংশনটি কল করতাম । আমার ক্ষেত্রে, আমি রূপান্তর এবং পরবর্তী কলটির মধ্যে সামান্য ওভারল্যাপ চেয়েছিলাম, আপনি আমার উদাহরণে দেখতে পাবেন:

var transitionDuration = 400;

selectedItems.transition().duration(transitionDuration).style("opacity", .5);

setTimeout(function () {
  sortControl.forceSort();
}, (transitionDuration * 0.75)); 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.