Search code examples
javascriptjqueryjsond3.jsspectrumjs

D3.js color the node circles with a function using spectrum.js


For each node, i have a circle which I color with the help of a function ColorType(d):

 node.append("circle")
     .attr("r", 20)
     .attr("y", -25)
     .style("fill", function(d) { return ColorType(d); })
     .style("stroke-width",0.5)
     .style("stroke",'black')
     .attr("opacity", "1");

My ColorType function is

function ColorType(d){
    for (var i = 0; i < TypesTab.length; i++) {
        if (d.type == TypesTab[i].type) { return ColorAction;}
    }   
}

in the above function, d.type is the type of my node (see below the json file strucutre). And TypesTab[i].type is each of my types stored separately in types, checking if the node type is the same as one of the value of the type in types, if so then applies the ColorAction which colors the node circle.

and here is the ColorAction code, which is embedded in each color picker container that is appended to each type in types, the list which is inserted to #filterColor html dom. so each type has a color picker container which is supposed to color its own type only.

$(document).ready(function () {
    $.getJSON("databeta.json", function (obj) {
        $('#filterColor').data('types', obj.types.map(function (o) {
            // console.log(o.type);
            return o.type;
        })).append(obj.types.map(function (o) {
            return '<li>' + o.type + '<input class="color-picker" type="text"/></li>';
        }).join(''));

        var data = $('#filterColor').data('types'); //stores all types

        mynodes = obj.nodes;
        console.log("mynodes : ", mynodes); //array of all my nodes
        console.log("mynodes : ", mynodes[3].type); //reading the type of the fourth object in the nodes array

        $("#filterColor .color-picker").each(function(){
            $(this).spectrum({
                color: (function (m, s, c) {
                    return (c ? arguments.callee(m, s, c - 1) : '#') +
                        s[m.floor(m.random() * s.length)]
                })(Math, '0123456789ABCDEF', 5), //generate random initial color for each container
                preferredFormat: "rgb",
                showInput: true,
                showPalette: true,
                showAlpha: true,
                palette: [["red", "rgba(0, 255, 0, .5)", "rgb(0, 0, 255)"]],
                change: function(color) {
                    MyNode = d3.select("#node").selectAll(".entreprise").select("circle");
                    MyNode.style("fill", function(d) {
                        return d3.rgb(color.toHexString())
                    });
                    Coloration = d3.rgb(color.toHexString());
                }
            });
        });

    });
});

the problem is that when i hardcode the type in the ColorType(d) function,

if (d.type == "school") { return ColorAction;}

it successfully colors the school typed nodes only. However, if i want to make it dynamic so that it colors the nodes with the type that the color picker is assigned to, it fails, because I can't make the connection with the each of o.type. So the question is to pass the each of o.type into the ColorAction and/or ColorType(d) so that each container only colors the nodes of its own type.

Here is an unsuccessfull attempt, because it doesn't take into consideration the o.type and reads the type in types from a global variable (TypesTab) that holds all types in types:

function ColorType(d){
    for (var i = 0; i < TypesTab.length; i++) {
        if (d.type == TypesTab[i].type) { return ColorAction;}
    }

}

The below is the json structure:

{
    "nodes": [
        {
        "type": "school",
        "country": "US",
        "name": "saint peter's",
        "id": 1006
        },
        {
        "type": "univeristy",
        "country": "Brazil",
        "name": "saint joseph's",
        "id": 1007
        }        
        ...
    ],
    "links": [
            {
            "source": 1006,
            "target": 1007,
            "value": 20            
        },
       ...

    ],
    "types": [
                {
                    "type": "school",
                    "image": "image01"
                },
                {
                    "type": "univeristy",
                    "image": "image02"
                },
                {
                    "type": "company",
                    "image": "image03"
                },
                ...
            ]   
}

Solution

  • This how I would read / import JSON. Inside the for in is basic, so you would need to change that part to suit your needs.

    d3.json("data.json", function (error, data) { console.log(d3.values(data)); // do this as a check for (var d in data) { d.nodes = +d.nodes; d.links = +d.links; d.types = +d.types; } // svg can go here })