如何更改节点的不透明度?

时间:2019-12-02 02:42:42

标签: javascript d3.js svg d3-force-directed

场景:

在将鼠标悬停在特定节点上时,我试图通过更改不透明度来突出显示该节点及其所有相互连接的节点,并且所有其他节点都应该模糊。

期望: 将鼠标悬停在某个节点上时,该节点及其所有互连节点的不透明度应为1,而其他节点应使用较小的不透明度进行模糊处理。

现有功能: 当我第一次在任何节点上悬停时,它无法按预期工作。但是从第二次开始,它就可以正常工作了。

请参考jsfiddle:jsfiddle

var nodeElements =  g.append("g")
  .attr("class", "nodes")
  .selectAll("circle")
  .data(graph.nodes)
  .enter().append("circle")
  .attr("r", 60)

  .attr("stroke", "#fff")
  .attr('stroke-width', 21)
  .attr("id", function(d) { return d.id })
   //.attr("fill", function(d) {return color(d.id)}) 
     .attr('fill', function(d, i) { return 'url(#grad' + i + ')'; })
     .on('contextmenu', function(d){ 
        d3.event.preventDefault();
        menu(d3.mouse(svg.node())[0], d3.mouse(svg.node())[1]);
    })
      .on('mouseover', selectNode)
      .on('mouseout', releaseNode)
  .call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended));


function selectNode(selectedNode) {
  var neighbors = getNeighbors(selectedNode)
        nodeElements.transition().duration(500)
        .attr('opacity', function(node) {
        return setOpacity(node,neighbors, selectedNode);
   })
   .attr('r', function(node) {
        return getNodeRadius(node,neighbors);
   });
   nodeElements.attr('fill', function(node) {
        // send selectedNode to your getNodeColor
        return getNodeColor(node,neighbors,selectedNode);
    })
   textElements.style('font-size', function(node) {
    return getTextColor(node, neighbors)
  })
  textElements.attr('opacity', function(node) {
        return setOpacity(node,neighbors, selectedNode);
   })

  linkElements.style('stroke', function(link) {
    return getLinkColor(selectedNode, link)
  })
}

function releaseNode() {
nodeElements
.attr('r', 60)
.attr('fill', function(d, i) { return 'url(#grad' + i + ')'; })
 .attr('opacity', 1);

linkElements.style('stroke', 'grey');
textElements.attr('opacity','1');
}



 function setOpacity(node, neighbors, selectedNode) {
        if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) {
            return 1;
        } else {
            return 0.3;
        }
    }

1 个答案:

答案 0 :(得分:2)

解决方案非常简单:请勿使用attr设置不透明度,而应使用style

nodeElements.transition()
    .duration(500)
    .style('opacity', function(node) {
        return setOpacity(node,neighbors, selectedNode);
    })

以下是仅有更改的代码:https://jsfiddle.net/uye24zjn/

说明

解释有点复杂。首先,请记住,您从未设置过任何不透明度,无论是使用attr还是style

转换不透明度时,D3使用相应的方法(attrstyle)使用吸气剂检索原始值。问题就来了:因为您从未使用attr方法设置任何不透明度,所以使用attr作为获取方法的先前值为null。但是,使用style的值为1

const circle = d3.select("g")
  .append("circle")
  .attr("r", 50);

console.log("The opacity value using 'attr' as a getter is: " + circle.attr("opacity"))
console.log("The opacity value using 'style' as a getter is: " + circle.style("opacity"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
  <g transform="translate(150,75)"></g>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

其结果是D3将尝试从null(零)过渡到1,并且您会看到圆圈在过渡开始时消失了。作为演示,将鼠标悬停在圆圈上:

const circle = d3.select("g")
  .append("circle")
  .attr("r", 50);

circle.on("mouseover", function() {
  d3.select(this).transition()
    .duration(1000)
    .attr("opacity", function() {
      return 1
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
  <g transform="translate(150,75)"></g>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

仅在第一次将鼠标悬停时会发生此问题(就像您的代码一样),因为将鼠标悬停在圆圈上后,不透明度被设置为属性,并且当nullattr时将不再存在attr用作吸气剂。

通常,使用style设置属性,然后使用style设置样式。换句话说:使用uri = URI.parse("https://api.wappalyzer.com/lookup/v1/?url=https://example.com") request = Net::HTTP::Get.new(uri) request["X-Api-Key"] = "wappalyzer.api.demo.key" req_options = { use_ssl: uri.scheme == "https", } response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http| http.request(request) end 来设置使用CSS文件所做的任何事情。