首页 > 解决方案 > d3.js selectAll 过滤器返回未定义

问题描述

以下基于:http ://bl.ocks.org/sjengle/5432087

我已经在完整代码中定义了节点标签。但是当我使用鼠标悬停功能时:

function mouseovered(d) {
    console.log("mouseOver");
    //d3.select(this).style("font-weight", 700);
    d3.select("#plot").selectAll(".nodeText")
        .filter(function(l) { return l.target === d.name || l.source === d.name; })
        .style("font-weight", 700);
}

过滤不起作用,当通过调试器运行时, l 未定义。什么可能导致 l 未定义?

编辑。似乎 l 没有属性 l.target 或 l.source

完整代码如下:

function sep_script () {

var diameter = 1060;
var radius = diameter / 2;
var margin = 240;

// Generates a tooltip for a SVG circle element based on its ID
function addTooltip(circle) {
    var x = parseFloat(circle.attr("cx"));
    var y = parseFloat(circle.attr("cy"));
    var r = parseFloat(circle.attr("r"));
    var text = circle.attr("id");

    var tooltip = d3.select("#plot")
        .append("text")
        .text(text)
        .attr("x", x)
        .attr("y", y)
        .attr("dy", -r * 2)
        .attr("id", "tooltip");

    var offset = tooltip.node().getBBox().width / 2;

    if ((x - offset) < -radius) {
        tooltip.attr("text-anchor", "start");
        tooltip.attr("dx", -r);
    }
    else if ((x + offset) > (radius)) {
        tooltip.attr("text-anchor", "end");
        tooltip.attr("dx", r);
    }
    else {
        tooltip.attr("text-anchor", "middle");
        tooltip.attr("dx", 0);
    }
}

// Draws an arc diagram for the provided undirected graph
function drawGraph(graph) {
    // create svg image
    var svg  = d3.select("body").select("#circle")
        .append("svg")
        .attr("width", diameter)
        .attr("height", diameter);

    // draw border around svg image
    // svg.append("rect")
    //     .attr("class", "outline")
    //     .attr("width", diameter)
    //     .attr("height", diameter);

    // create plot area within svg image
    var plot = svg.append("g")
        .attr("id", "plot")
        .attr("transform", "translate(" + radius + ", " + radius + ")");

    // draw border around plot area
    // plot.append("circle")
    //     .attr("class", "outline")
    //     .attr("r", radius - margin);

    // fix graph links to map to objects instead of indices
    graph.links.forEach(function(d, i) {
        d.source = isNaN(d.source) ? d.source : graph.nodes[d.source];
        d.target = isNaN(d.target) ? d.target : graph.nodes[d.target];
    });

    // calculate node positions
    circleLayout(graph.nodes);

    // draw edges first
    //drawLinks(graph.links);
    // draw Curves
    //drawCurves(graph.links);

    // NEW draw bundled Curves (Not bundled as I wish)
    drawBundledButNotCurves(graph.links);
    // NEW draw bundled Curves
    //drawBundledCurves(graph.links);

    // draw nodes last
    drawNodes(graph.nodes);
}

// Calculates node locations
function circleLayout(nodes) {
    // sort nodes by group
    nodes.sort(function(a, b) {
        return a.group - b.group;
    });

    // use to scale node index to theta value
    var scale = d3.scale.linear()
        .domain([nodes.length, 0])
        .range([Math.PI, 3 * Math.PI]);

    // calculate theta for each node
    nodes.forEach(function(d, i) {
        // calculate polar coordinates
        var theta  = scale(i);
        var radial = radius - margin;

        // convert to cartesian coordinates
        d.x = radial * Math.sin(theta);
        d.y = radial * Math.cos(theta);
    });
}

// Draws nodes with tooltips
function drawNodes(nodes) {
    // OLD used to assign nodes color by group
    //var color = d3.scale.category20();

    // NEW colors for nodes with white ones to make categories look bundled
    //var colors = ['steelblue', '#ffffff00'];
    // colors for nodes to hide circles
    var colors = ['#ffffff00'];   
    var color = d3.scale.ordinal().range(colors);

    d3.select("#plot").selectAll(".node")
        .data(nodes)
        .enter()
        .append("circle")
        .attr("class", "node")
        .attr("id", function(d, i) { return d.name; })
        .attr("cx", function(d, i) { return d.x; })
        .attr("cy", function(d, i) { return d.y; })
        .attr("r", 5)
        .style("fill",   function(d, i) { return color(d.group); })
        .on("mouseover", function(d, i) { addTooltip(d3.select(this)); })
        .on("mouseout",  function(d, i) { d3.select("#tooltip").remove(); });


    // NEW scale for rotation
    var rotationScale = d3.scale.pow()
        .exponent(1.9)
        .range([-90, 90])
        .domain([-290,290]);

    // NEW define 
    // NEW add text labels
    d3.select("#plot").selectAll(".nodeText") //???? ".nodeText"
        .data(nodes)
        .enter()
        .append("text")
        .attr("class", "nodeText")
        .attr("dy", ".31em")
        .attr("transform", function(d) { return "translate(" + (d.x) + ", " + (d.y) + ")rotate(" + (d.x < 0 ? rotationScale(-d.y) : rotationScale(d.y)) + ")translate(" + (d.x < 0 ? (-8) : (8)) + ", " + 0 + ")"})
        //          sets the origin of rotation to the node's location ^^^^^^^^^^        ^^rotates the label for right half the other way round then the left half      ^^and shifts the label a bit from the circle
        .style("text-anchor", function(d) { return d.x > 0 ? "start" : "end"; })
        //.style("text_anchor", "bottom")
        .text(function(d) { return d.name; })
        //.on("mouseover", mouseovered)
        //.on("mouseout", mouseouted);
        .on("mouseover", mouseovered)
        .on("mouseout", mouseouted);

}

// NEW Functions for mouseovered and mouseouted
// https://gist.github.com/hughlomas/1678703    - simple mouseover functions
function mouseovered(d) {
    console.log("mouseOver");
    //d3.select(this).style("font-weight", 700);
    d3.select("#plot").selectAll(".nodeText")
        .filter(function(l) { return l.name === d.name || l.name === d.name; })
        //.filter(function(l) { return console.log(l)})
        .style("font-weight", 700);
}

function mouseouted(d) {
    console.log("mouseOut");
    d3.select(this).style("font-weight", 400);
    d3.select("#plot").selectAll("text").style("font-weight", 400);
}

// NEW added for color ---
var colorScale = d3.scale.quantize()   .range(["#ffffff00","#8bc3f6","#8bc3f6","#8bc3f6","#51acff","#51acff","#51acff","#2f86ff","#2f86ff","#2f86ff","#0051ff","#0051ff","#0051ff"])
.domain([-0.06666666666666,0.8]);
// added for color ---

// NEW Draws bundled curved edges between nodes (Not bundled as I wish)
function drawBundledButNotCurves(links) {
    // https://stackoverflow.com/questions/34263110/d3-js-edge-bundling-without-hierachy
    d3.select("#plot").selectAll(".link")
        .data(links)
        .enter()
        .append("path")
        .attr("class", "link")
        .attr("d", function(d){
          var lineData = [
          {
            x: Math.round(d.target.x),
            y: Math.round(d.target.y)
          }, {
          x: Math.round(d.target.x) - Math.round(d.target.x)/3,
            y: Math.round(d.target.y) - Math.round(d.target.y)/3
          }, 
          {
          x: Math.round(d.source.x) - Math.round(d.source.x)/3,
            y: Math.round(d.source.y) - Math.round(d.source.y)/3
          },{
            x: Math.round(d.source.x),
            y: Math.round(d.source.y)
          }];
          return `M${lineData[0].x},${lineData[0].y}C${lineData[1].x},${lineData[1].y},${lineData[2].x},${lineData[2].y},${lineData[3].x},${lineData[3].y} `;
        })
        // added for color
        .style("stroke", function(d){
            return colorScale(d.value)
        });
}


d3.json("flare_newC.json", drawGraph);
}

这是数据:

{"nodes": [{"name": "OP PIK_01.1 Rozvoj výzkumu a vývoje pro inovace", "group": 1}, {"name": "OP PIK_01.2 Rozvoj podnikání a konkurenceschopnosti malých a středních podniků", "group": 1}, {"name": "OP PIK_01.3 Účinné nakládání energií, rozvoj energetické infrastruktury a obnovitelných zdrojů energie, podpora zavádění nových technologií v oblasti nakládání energií a druhotných surovin", "group": 1}, {"name": "OP PIK_01.4 Rozvoj vysokorychlostních přístupových sítí k internetu a informačních a komunikačních technologií", "group": 1}, {"name": "OP PIK_01.5 Technická pomoc", "group": 1}, ...

, {"name": "", "group": 2}, {"name": "", "group": 4}, {"name": "", "group": 6}, {"name": "", "group": 8}, {"name": "", "group": 10}, {"name": "", "group": 12}, {"name": "", "group": 14}, {"name": "", "group": 16}

], "links": [{"value": 0.13757455268389662, "target": 1, "source": 0}, {"value": 0.07236842105263158, "target": 2, "source": 0}, {"value": 0.03948896631823461, "target": 3, "source": 0}, {"value": 0.0, "target": 4, "source": 0}, {"value": 0.007836990595611285, "target": 5, "source": 0}, {"value": 0.009244992295839754, "target": 6, "source": 0}, {"value": 0.0005341167044999333, "target": 7, "source": 0}, {"value": 0.0, "target": 8, "source": 0}, {"value": 0.06844336765596608, "target": 9, "source": 0}, {"value": 0.0, "target": 10, "source": 0}, {"value": 0.0014781966001478197, "target": 11, "source": 0}, {"value": 0.0, "target": 12, "source": 0}, {"value": 0.0, "target": 13, "source": 0}, {"value": 0.0, "target": 14, "source": 0}, {"value": 0.0, "target": 15, "source": 0}, {"value": 0.0, "target": 16, "source": 0}, {"value": 0.0, "target": 17, "source": 0}, {"value": 0.0, "target": 18, "source": 0}, {"value": 0.004398826979472141, "target": 19, "source": 0}, {"value": 0.0018248175182481751, "target": 20, "source": 0}, {"value": 0.0, "target": 21, "source": 0}, {"value": 0.0022197558268590455, "target": 22, "source": 0}, {"value": 0.0, "target": 23, "source": 0}, ... ]}

标签: javascriptd3.jsfilterdata-visualizationmouseover

解决方案


推荐阅读