বাহিনী-নির্দেশিত লেআউটে নতুন নোড যুক্ত করা হচ্ছে


89

স্ট্যাক ওভারফ্লোতে প্রথম প্রশ্ন, তাই আমার সহ্য করুন! আমি d3.js এ নতুন, তবে অন্যরা এটির দ্বারা কী অর্জন করতে সক্ষম হয়েছে তা দ্বারা আমি অবিরত অবাক হয়েছি ... এবং আমি নিজেই এটির সাথে সামান্য অগ্রগতি করতে পেরেছি বলে প্রায় অবাক হয়ে গিয়েছি! স্পষ্টতই আমি কিছু ছোঁড়াচ্ছি না, তাই আমি আশা করি যে এখানকার দয়ালু প্রাণীরা আমাকে আলো দেখাতে পারে।

আমার উদ্দেশ্য হ'ল পুনরায় ব্যবহারযোগ্য জাভাস্ক্রিপ্ট ফাংশন করা যা কেবল নিম্নলিখিতটি করে:

  • একটি নির্দিষ্ট ডিওএম উপাদানটিতে একটি ফাঁকা বল-নির্দেশিত গ্রাফ তৈরি করে
  • তাদের মধ্যে সংযোগ নির্দিষ্ট করে সেই গ্রাফটিতে আপনাকে লেবেলযুক্ত, চিত্র-বহনকারী নোডগুলি যুক্ত করতে এবং মুছতে দেয়

আমি http://bl.ocks.org/950642 কে একটি প্রারম্ভিক পয়েন্ট হিসাবে নিয়েছি , যেহেতু এটি মূলত আমি যে ধরণের লেআউটটি তৈরি করতে সক্ষম হতে চাই:

এখানে চিত্র বর্ণনা লিখুন

আমার কোডটি কেমন দেখাচ্ছে তা এখানে:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="jquery.min.js"></script>
    <script type="text/javascript" src="underscore-min.js"></script>
    <script type="text/javascript" src="d3.v2.min.js"></script>
    <style type="text/css">
        .link { stroke: #ccc; }
        .nodetext { pointer-events: none; font: 10px sans-serif; }
        body { width:100%; height:100%; margin:none; padding:none; }
        #graph { width:500px;height:500px; border:3px solid black;border-radius:12px; margin:auto; }
    </style>
</head>
<body>
<div id="graph"></div>
</body>
<script type="text/javascript">

function myGraph(el) {

    // Initialise the graph object
    var graph = this.graph = {
        "nodes":[{"name":"Cause"},{"name":"Effect"}],
        "links":[{"source":0,"target":1}]
    };

    // Add and remove elements on the graph object
    this.addNode = function (name) {
        graph["nodes"].push({"name":name});
        update();
    }

    this.removeNode = function (name) {
        graph["nodes"] = _.filter(graph["nodes"], function(node) {return (node["name"] != name)});
        graph["links"] = _.filter(graph["links"], function(link) {return ((link["source"]["name"] != name)&&(link["target"]["name"] != name))});
        update();
    }

    var findNode = function (name) {
        for (var i in graph["nodes"]) if (graph["nodes"][i]["name"] === name) return graph["nodes"][i];
    }

    this.addLink = function (source, target) {
        graph["links"].push({"source":findNode(source),"target":findNode(target)});
        update();
    }

    // set up the D3 visualisation in the specified element
    var w = $(el).innerWidth(),
        h = $(el).innerHeight();

    var vis = d3.select(el).append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    var force = d3.layout.force()
        .nodes(graph.nodes)
        .links(graph.links)
        .gravity(.05)
        .distance(100)
        .charge(-100)
        .size([w, h]);

    var update = function () {

        var link = vis.selectAll("line.link")
            .data(graph.links);

        link.enter().insert("line")
            .attr("class", "link")
            .attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; });

        link.exit().remove();

        var node = vis.selectAll("g.node")
            .data(graph.nodes);

        node.enter().append("g")
            .attr("class", "node")
            .call(force.drag);

        node.append("image")
            .attr("class", "circle")
            .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
            .attr("x", "-8px")
            .attr("y", "-8px")
            .attr("width", "16px")
            .attr("height", "16px");

        node.append("text")
            .attr("class", "nodetext")
            .attr("dx", 12)
            .attr("dy", ".35em")
            .text(function(d) { return d.name });

        node.exit().remove();

        force.on("tick", function() {
          link.attr("x1", function(d) { return d.source.x; })
              .attr("y1", function(d) { return d.source.y; })
              .attr("x2", function(d) { return d.target.x; })
              .attr("y2", function(d) { return d.target.y; });

          node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
        });

        // Restart the force layout.
        force
          .nodes(graph.nodes)
          .links(graph.links)
          .start();
    }

    // Make it all go
    update();
}

graph = new myGraph("#graph");

// These are the sort of commands I want to be able to give the object.
graph.addNode("A");
graph.addNode("B");
graph.addLink("A", "B");

</script>
</html>

আমি যখনই একটি নতুন নোড যুক্ত করব তখন এটি বিদ্যমান সমস্ত নোডকে পুনরায় লেবেল দেয়; একে অপরের উপরে এই গাদা এবং জিনিসগুলি কুৎসিত হতে শুরু করে। আমি বুঝতে পারি এটি কেন: কারণ যখন আমি update()একটি নতুন নোড যুক্ত করার পরে ফাংশনটি ফাংশন বলি , এটি node.append(...)সম্পূর্ণ ডেটা সেটকে একটি করে। আমি যোগ করছি কেবল নোডের জন্য এটি কীভাবে করা যায় তা আমি বুঝতে পারি না ... এবং আমি কেবল node.enter()একটি নতুন উপাদান তৈরি করতে স্পষ্টতই ব্যবহার করতে পারি, যাতে নোডের সাথে আবদ্ধ হওয়া অতিরিক্ত উপাদানগুলির জন্য এটি কাজ করে না । আমি এটা কিভাবে ঠিক করবো?

আপনি এই সমস্যার যে কোনও বিষয়ে দিতে সক্ষম যে কোনও নির্দেশিকা জন্য আপনাকে ধন্যবাদ!

সম্পাদনা করা হয়েছে কারণ আমি আগে উল্লেখ করা বেশ কয়েকটি অন্যান্য বাগের উত্স দ্রুত স্থির করেছিলাম

উত্তর:


152

অনেক ঘন্টা ধরে এই কাজটি পেতে অক্ষম হওয়ার পরে, অবশেষে আমি একটি ডেমো জুড়ে হোঁচট খেয়েছি যা আমি মনে করি না যে কোনও ডকুমেন্টেশনের সাথে যুক্ত রয়েছে: http://bl.ocks.org/1095795 :

এখানে চিত্র বর্ণনা লিখুন

এই ডেমোতে কীগুলি অন্তর্ভুক্ত ছিল যা শেষ পর্যন্ত আমাকে সমস্যার ক্র্যাক করতে সহায়তা করেছিল।

কোনও ভেরিয়েবলকে enter()বরাদ্দ করে enter()এবং তারপরে সংযোজন করে কোনওটিতে একাধিক অবজেক্ট যুক্ত করা যায়। এইবার বুঝতে পারছি. দ্বিতীয় সমালোচনা অংশটি হ'ল নোড এবং লিঙ্ক অ্যারেগুলি অবশ্যই এর উপর ভিত্তি করে তৈরি করা উচিত force()- নইলে গ্রাফ এবং মডেল নোডগুলি মোছার সাথে যুক্ত হওয়ার সাথে সাথে সিঙ্কের বাইরে চলে যাবে।

কারণ এর পরিবর্তে যদি নতুন অ্যারে তৈরি করা হয় তবে এতে নিম্নলিখিত বৈশিষ্ট্যগুলির ঘাটতি থাকবে :

  • সূচক - নোড অ্যারের মধ্যে নোডের শূন্য-ভিত্তিক সূচক।
  • এক্স - বর্তমান নোড পজিশনের এক্স-কো-অর্ডিনেট।
  • y - বর্তমান নোড পজিশনের y- স্থানাঙ্ক।
  • px - পূর্ববর্তী নোড পজিশনের এক্স-কো-অর্ডিনেট।
  • পাই - পূর্ববর্তী নোড পজিশনের y- স্থানাঙ্ক।
  • স্থির - একটি বুলিয়ান যা নোড অবস্থান লক করা আছে তা নির্দেশ করে।
  • ওজন - নোড ওজন; সম্পর্কিত লিঙ্কের সংখ্যা।

এই বৈশিষ্ট্যগুলিতে কল করার জন্য কঠোরভাবে প্রয়োজন force.nodes()হয় না, তবে এগুলি উপস্থিত না থাকলে প্রথম কলের মাধ্যমে এলোমেলোভাবে সূচনা করা force.start()হবে।

যদি কেউ কৌতূহলী হন তবে কার্যকারী কোডটি দেখতে এরকম দেখাচ্ছে:

<script type="text/javascript">

function myGraph(el) {

    // Add and remove elements on the graph object
    this.addNode = function (id) {
        nodes.push({"id":id});
        update();
    }

    this.removeNode = function (id) {
        var i = 0;
        var n = findNode(id);
        while (i < links.length) {
            if ((links[i]['source'] === n)||(links[i]['target'] == n)) links.splice(i,1);
            else i++;
        }
        var index = findNodeIndex(id);
        if(index !== undefined) {
            nodes.splice(index, 1);
            update();
        }
    }

    this.addLink = function (sourceId, targetId) {
        var sourceNode = findNode(sourceId);
        var targetNode = findNode(targetId);

        if((sourceNode !== undefined) && (targetNode !== undefined)) {
            links.push({"source": sourceNode, "target": targetNode});
            update();
        }
    }

    var findNode = function (id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return nodes[i]
        };
    }

    var findNodeIndex = function (id) {
        for (var i=0; i < nodes.length; i++) {
            if (nodes[i].id === id)
                return i
        };
    }

    // set up the D3 visualisation in the specified element
    var w = $(el).innerWidth(),
        h = $(el).innerHeight();

    var vis = this.vis = d3.select(el).append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    var force = d3.layout.force()
        .gravity(.05)
        .distance(100)
        .charge(-100)
        .size([w, h]);

    var nodes = force.nodes(),
        links = force.links();

    var update = function () {

        var link = vis.selectAll("line.link")
            .data(links, function(d) { return d.source.id + "-" + d.target.id; });

        link.enter().insert("line")
            .attr("class", "link");

        link.exit().remove();

        var node = vis.selectAll("g.node")
            .data(nodes, function(d) { return d.id;});

        var nodeEnter = node.enter().append("g")
            .attr("class", "node")
            .call(force.drag);

        nodeEnter.append("image")
            .attr("class", "circle")
            .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
            .attr("x", "-8px")
            .attr("y", "-8px")
            .attr("width", "16px")
            .attr("height", "16px");

        nodeEnter.append("text")
            .attr("class", "nodetext")
            .attr("dx", 12)
            .attr("dy", ".35em")
            .text(function(d) {return d.id});

        node.exit().remove();

        force.on("tick", function() {
          link.attr("x1", function(d) { return d.source.x; })
              .attr("y1", function(d) { return d.source.y; })
              .attr("x2", function(d) { return d.target.x; })
              .attr("y2", function(d) { return d.target.y; });

          node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
        });

        // Restart the force layout.
        force.start();
    }

    // Make it all go
    update();
}

graph = new myGraph("#graph");

// You can do this from the console as much as you like...
graph.addNode("Cause");
graph.addNode("Effect");
graph.addLink("Cause", "Effect");
graph.addNode("A");
graph.addNode("B");
graph.addLink("A", "B");

</script>

4
যখন নতুন ডেটা যুক্ত হয় তার force.start()পরিবর্তে ব্যবহার করা force.resume()মূল বিষয় ছিল। অনেক ধন্যবাদ!
মৌগীপ

এটা সত্যিই দারুন. শীতল হোন যদি এটি জুম স্তরটি অটস্কিল করে (তবে সবকিছুই মাপসই করে চার্জ হ্রাস করতে পারে?) সুতরাং যে বাক্সটি এটি আঁকছিল তার আকারের মধ্যে সমস্ত কিছু লাগানো
রব গ্রান্ট

4
ক্লিন কোড উদাহরণের জন্য +1। মিঃ বোস্টকের উদাহরণের চেয়ে আমি এটির চেয়ে ভাল পছন্দ করি কারণ এটি দেখায় যে কীভাবে কোনও বস্তুর মধ্যে আচরণকে সজ্জিত করা যায়। সাবাশ. (D3 তে উদাহরণ লাইব্রেরির সাথে যোগ করে বিবেচনা করুন?)
fearless_fool

ঐটা সুন্দর! আমি এখন কয়েক দিনের জন্য ডি 3 দিয়ে ফোর্সগ্রাফ কীভাবে ব্যবহার করব তা শিখছি এবং এটি দেখে আসার এটি সবচেয়ে সুন্দর উপায়। আপনাকে অনেক ধন্যবাদ!
লুকাস আজেভেদো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.