javascript - 如何在 D3 force layout on load 中为 3 个节点指定 3 种不同的自定义颜色

标签 javascript css d3.js force-layout

我正在使用 D3 api 按顺序显示一些节点,这些节点以相同的颜色进入页面。当我将鼠标悬停在一个节点上时,它会变成其他颜色。但我想要在加载时为节点(不同于其他节点)使用固定颜色。我正在使用这个 api.. 请帮助我...

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .node circle {
stroke: white;
stroke-width: 1.5px;
opacity: 1.0;
   }

line {
stroke: black;
stroke-width: 1.5px;
stroke-opacity: 1.0;
 }
 </style>
 <body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
    data = {
        nodes : [ {
            size : 10
        }, {
            size : 5
        }, {
            size : 2
        }, {
            size : 3

        } ],
        links : [ {
            source : 0,
            target : 1
        }, {
            source : 0,
            target : 2

        } ]
    }

    var mouseOverFunction = function(d,i) {
        var circle = d3.select(this);
        //$ fill = d3.scale.category20();
        node.transition(500).style("opacity", function(o) {
            return isConnected(o, d) ? 1.0 : 0.2;
        }).style("fill", function(o) {
            if (isConnectedAsTarget(o, d) && isConnectedAsSource(o, d)) {
                fillcolor = 'green';
            } else if (isConnectedAsSource(o, d)) {
                fillcolor = 'red';
            } else if (isConnectedAsTarget(o, d)) {
                fillcolor = 'blue';
            } else if (isEqual(o, d)) {
                fillcolor = "hotpink";
            } else if(isNot(o,d)){

              //here the output will shown when no mouse event is occured


            }
            return fillcolor;
        });

        link
                .transition(500)
                .style("stroke-opacity", function(o) {
                    return o.source === d || o.target === d ? 1 : 0.2;
                })
                .transition(500)
                .attr(
                        "marker-end",
                        function(o) {
                            return o.source === d || o.target === d ? "url(#arrowhead)"
                                    : "url()";
                        });

        circle.transition(500).attr("r", function() {
            return 1.4 * node_radius(d)
        });
    }

    var mouseOutFunction = function() {
        var circle = d3.select(this);

        node.transition(500);

        link.transition(500);

        circle.transition(500).attr("r", node_radius);
    }

    function isConnected(a, b) {
        return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b)
                || a.index == b.index;
    }

    function isConnectedAsSource(a, b) {
        return linkedByIndex[a.index + "," + b.index];
    }

    function isConnectedAsTarget(a, b) {
        return linkedByIndex[b.index + "," + a.index];
    }

    function isEqual(a, b) {
        return a.index == b.index;
    }

        //here i have trying to make root  node a separate color and the child nodes two separate colors
    function isNot(a,b){

    return d3.scale.category20()(i);
    }


    function tick() {
        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 + ")";
        });
    }

    function node_radius(d) {
        return Math.pow(40.0 * d.size, 1 / 3);
    }

    var width = 1000;
    var height = 500;

    var nodes = data.nodes
    var links = data.links

    var force = d3.layout.force().nodes(nodes).links(links).charge(-3000)
            .friction(0.6).gravity(0.6).size([ width, height ]).start();

    var linkedByIndex = {};
    links.forEach(function(d) {
        linkedByIndex[d.source.index + "," + d.target.index] = true;
    });

    var svg = d3.select("body").append("svg").attr("width", width).attr(
            "height", height);

    var link = svg.selectAll("line")
                .data(links)
                .enter()
                .append("line");

    var node = svg.selectAll(".node")
                .data(nodes)
                .enter()
        .append("g")
        .style("fill", function (d) {
                    return '#1f77b4';
                })  
        .attr("class", "node")
                .attr("cx",function(d) {
                    return d.x;
                })
            .attr("cy",function(d) {
                    return d.y;
                })  
        //.attr("fill",function(d){return color(d.range);})
        .call(force.drag);

    node.append("circle")
                .attr("r", node_radius)
                .on("mouseover", mouseOverFunction)
                .on("mouseout", mouseOutFunction);

    svg.append("marker")
                .attr("id", "arrowhead")
                .attr("refX", 6 + 7) // Controls the shift of the arrow head along the path
        .attr("refY", 2)
                .attr("markerWidth", 6)
                .attr("markerHeight", 4)
                .attr("orient", "auto")
                .append("path")
                .attr("d", "M 0,0 V 4 L6,2 Z");

    link.attr("marker-end", "url()");

    force.on("tick", tick);
</script>
 </body>

This is the output I got

But This is what I want..

最佳答案

我认为您的代码已经快完成了。在鼠标悬停时,您应该修改节点的“填充”css 属性。

为此,在 d3 中您必须使用:

node.append("circle")
    .attr("r", node_radius)
    .on("mouseover",mouseOverFunction)

就像你一样。 在 moueOverFunction 中,您有两种选择来获取给定节点的属性:

1) 从节点的属性获取颜色:

function mouseoverFunction(node) {
    if(node.size<10) {
        return 'blue'
    } else {
        return 'red'
    }
}

2) 从节点在数据数组中的位置获取颜色:

function mouseoverFunction(node,index) {
    if(index<2) {
        // Will color the two first nodes blue
        return 'blue'
    } else {
        // All others will be red
        return 'red'
    }
}

最后我会针对你的具体问题做:

function mouseoverFunction(node,index) {
    if(index<3) {
        return ['red','green','blue'][index]
    } else {
        // index should be less than 3
        return 'black'
    }
}

关于javascript - 如何在 D3 force layout on load 中为 3 个节点指定 3 种不同的自定义颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20441421/

相关文章:

javascript - 使用 Backbone sync 与预先存在的 Javascript API

html - Node.js( express ): How to include correct value for 'src' attribute of an 'img' tag?

javascript - 如何在 Angular JS 中加载 CSV 文件来制作图表

javascript - 是否可以编写一个使所有浏览器标准兼容的 JavaScript 库?

javascript - 使用 window.getSelection() 选择单词和周围的单词

javascript - 为 json 合并 javascript 数组

css - 为什么 float 会导致顶部 margin 增加?

html - 如何将不同的背景图像 URL 添加到一个类中?

javascript - 如何将 data.key --> element.id 绑定(bind)到 d3js 中的现有标记上?

javascript - D3 在鼠标按下期间触发拖动