【问题标题】:D3 v4 change opacity for kontext related nodesD3 v4 更改 kontext 相关节点的不透明度
【发布时间】:2020-12-10 06:57:49
【问题描述】:

我对 D3 完全陌生,并试图解决以下场景。我有几个与上下文相关的节点。所有这些都可以按我的意愿正常显示,此外我还想添加一个 HTML 选择器按钮,它可以更改所有未选中节点的颜色和不透明度。

目标是通过更改非选定节点的颜色和不透明度来突出显示选择。我不想像 here 那样完全删除它们,因为某些节点将来会成为多个上下文的成员。

我认为我们社区的群体智能可能会有想法。提前致谢。

var graph = {
    nodes:[
        {id: "0001", name: "s02vmware", kontext: "Jira", group: 1},
        {id: "0002", name: "v133atlas", kontext: "Jira", group: 2},
        {id: "0003", name: "Linux", kontext: "Jira", group: 2},
        {id: "0004", name: "PostgreSQL", kontext: "Jira", group: 2},
        {id: "0005", name: "OpenSSH", kontext: "Jira", group: 2},
        {id: "0006", name: "Nginx", kontext: "Jira", group: 2},
        {id: "0007", name: "Confluence", kontext: "Jira", group: 3},
        {id: "0008", name: "Tomcat", kontext: "Jira", group: 3},
        {id: "0009", name: "Java", kontext: "Jira", group: 3},

        {id: "0010", name: "Test1", kontext: "Ivis", group: 1},
        {id: "0011", name: "Test2", kontext: "Ivis", group: 2},
        {id: "0012", name: "Test3", kontext: "Ivis", group: 2},
    ],
    links:[
        {source: "0001", target: "0002"},
        {source: "0002", target: "0003"},
        {source: "0004", target: "0003"},
        {source: "0005", target: "0003"},
        {source: "0006", target: "0003"},
        {source: "0007", target: "0003"},
        {source: "0008", target: "0007"},
        {source: "0009", target: "0007"},

        {source: "0010", target: "0012"},
        {source: "0011", target: "0010"},
        {source: "0012", target: "0011"},
    ]
};


var svg = d3.select("svg"),
    width = window.innerWidth,
    height = window.innerHeight;

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
 .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100))
 .force("charge", d3.forceManyBody())
 .force("center", d3.forceCenter(width / 2, height / 2))
 .force("attraceForce",d3.forceManyBody().strength(-80));

var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
    .attr("stroke-width", 2);

var node = svg.selectAll(".node")
            .data(graph.nodes)
            .enter().append("g")
            .attr("class", "node")
            .on("mouseover", mouseover)
            .on("mouseout", mouseout)
            /*
            .on("click", function(d) {      
                div.transition()        
                    .duration(200)      
                    .style("opacity", 0.9);     
                div .html((d.name) + "<br/>"  + d.close)    
                    .style("left", (d3.event.pageX) + "px")     
                    .style("top", (d3.event.pageY - 28) + "px")*/
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));

node.append("circle")
  .attr("r", 15)
  .attr("fill", function(d) { return color(d.group); });

node.append("text")
    .attr("dy", -20)
    .text(function(d) { return d.name; });

simulation
   .nodes(graph.nodes)
   .on("tick", ticked);

simulation.force("link")
   .links(graph.links);

function ticked() {
   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 dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
   d.fx = d3.event.x;
   d.fy = d3.event.y;
}

function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}

function mouseover() {
    d3.select(this).select("circle").transition()
        .duration(100)
        .attr("r", 20);
}

function mouseout() {
    d3.select(this).select("circle").transition()
        .duration(500)
        .attr("r", 15);
}
/* todo: add styles */
.vertical-grid{
    stroke:#ccc;
    
  }
  
  .ordinate-text{
    font-size:10px;
    transform:translateY(10px);
  }
  
  div.tooltip {
    position: absolute;
    text-align: center;
    width: auto;
    height: auto;
    padding: 2px;
    font: 12px sans-serif;
    background: lightsteelblue;
    border: 0px;
    border-radius: 8px;
    pointer-events: none;
    opacity:0;
    padding:5px;
  }
  
  .right-align{
    position:absolute;
    right:100px;
    
  }
  .box,
  .label{
      display:inline-block;
  }
  
  .box{
    width:10px;
    height:10px;
    margin:0px 10px;
  }
<!DOCTYPE html>

    <head>

        <meta charset = "utf-8">
        <link rel="stylesheet" type="text/css" href="style.css">
       
        <title>Ideal iDEP on D3.js</title>
        
   </head>


   <body>
      <!-- Kontext Option Button -->
      <select>
        <option value="01">01 - Jira</option>
        <option value="02">02 - Ivis</option>
        <option value="03">Whatever</option>
      </select>
      
      <!-- SVG as a canvas area -->
      <svg width="100%" height="100%"></svg>
      <!--<svg id="canvas" width="100%" height="100%"></svg> -->
      <!-- import d3.js library -->
      <script src="https://d3js.org/d3.v4.js"></script> 
      <!-- where the magic is happening -->    
      <script type="" src="appv4.js"></script>

   </body>

</html>

【问题讨论】:

    标签: javascript html d3.js graph


    【解决方案1】:

    您会希望选择菜单具有代表每个 kontext 的值:

      <select>
        <option value="Jira">01 - Jira</option>
        <option value="Ivis">02 - Ivis</option>
        <option value="All" selected>Whatever</option>
      </select>
    

    然后你会想听听这个改变。当它发生变化时,您会将所有节点恢复为正常状态,并筛选出具有与所选节点匹配的 kontext 的节点。

    因为您有两个不同的子元素,您可能希望以不同的方式更改颜色和不透明度。下面我先改变了标签和圆的不透明度,然后选择了每个节点的圆并改变了填充:

    d3.select("select").on("change", function() {
      var value = this.value;
      
     // Reset every node:
      node.style("opacity", 1) // change opacity back for every node
          .select("circle")    // select the circle to alter its color
          .style("fill", function(d) { return color(d.group); });
          
      // If "All" isn't selected, filter for the selected value:
      if(value != "All") {
        node.filter(function(d) { return d.kontext != value; })
            .style("opacity", 0.5) // Change the opacity of text and circle for filtered items
            .select("circle")      // select the circle to alter its color
            .style("fill","#aaa");
      }
    })
    

    综合起来我们得到:

    var graph = {
        nodes:[
            {id: "0001", name: "s02vmware", kontext: "Jira", group: 1},
            {id: "0002", name: "v133atlas", kontext: "Jira", group: 2},
            {id: "0003", name: "Linux", kontext: "Jira", group: 2},
            {id: "0004", name: "PostgreSQL", kontext: "Jira", group: 2},
            {id: "0005", name: "OpenSSH", kontext: "Jira", group: 2},
            {id: "0006", name: "Nginx", kontext: "Jira", group: 2},
            {id: "0007", name: "Confluence", kontext: "Jira", group: 3},
            {id: "0008", name: "Tomcat", kontext: "Jira", group: 3},
            {id: "0009", name: "Java", kontext: "Jira", group: 3},
    
            {id: "0010", name: "Test1", kontext: "Ivis", group: 1},
            {id: "0011", name: "Test2", kontext: "Ivis", group: 2},
            {id: "0012", name: "Test3", kontext: "Ivis", group: 2},
        ],
        links:[
            {source: "0001", target: "0002"},
            {source: "0002", target: "0003"},
            {source: "0004", target: "0003"},
            {source: "0005", target: "0003"},
            {source: "0006", target: "0003"},
            {source: "0007", target: "0003"},
            {source: "0008", target: "0007"},
            {source: "0009", target: "0007"},
    
            {source: "0010", target: "0012"},
            {source: "0011", target: "0010"},
            {source: "0012", target: "0011"},
        ]
    };
    
    
    var svg = d3.select("svg"),
        width = 500,
        height = 300;
    
    var color = d3.scaleOrdinal(d3.schemeCategory20);
    
    var simulation = d3.forceSimulation()
     .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100))
     .force("charge", d3.forceManyBody())
     .force("center", d3.forceCenter(width / 2, height / 2))
     .force("attraceForce",d3.forceManyBody().strength(10));
    
    var link = svg.append("g")
        .attr("class", "links")
        .selectAll("line")
        .data(graph.links)
        .enter().append("line")
        .attr("stroke-width", 2);
    
    var node = svg.selectAll(".node")
                .data(graph.nodes)
                .enter().append("g")
                .attr("class", "node")
                .on("mouseover", mouseover)
                .on("mouseout", mouseout)
                /*
                .on("click", function(d) {      
                    div.transition()        
                        .duration(200)      
                        .style("opacity", 0.9);     
                    div .html((d.name) + "<br/>"  + d.close)    
                        .style("left", (d3.event.pageX) + "px")     
                        .style("top", (d3.event.pageY - 28) + "px")*/
                .call(d3.drag()
                    .on("start", dragstarted)
                    .on("drag", dragged)
                    .on("end", dragended));
    
    node.append("circle")
      .attr("r", 15)
      .attr("fill", function(d) { return color(d.group); });
    
    node.append("text")
        .attr("dy", -20)
        .text(function(d) { return d.name; });
    
    simulation
       .nodes(graph.nodes)
       .on("tick", ticked);
    
    simulation.force("link")
       .links(graph.links);
    
    function ticked() {
       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 dragstarted(d) {
      if (!d3.event.active) simulation.alphaTarget(0.3).restart();
      d.fx = d.x;
      d.fy = d.y;
    }
    
    function dragged(d) {
       d.fx = d3.event.x;
       d.fy = d3.event.y;
    }
    
    function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
    }
    
    function mouseover() {
        d3.select(this).select("circle").transition()
            .duration(100)
            .attr("r", 20);
    }
    
    function mouseout() {
        d3.select(this).select("circle").transition()
            .duration(500)
            .attr("r", 15);
    }
    
    d3.select("select").on("change", function() {
      var value = this.value;
      
     // Reset every node:
      node.style("opacity", 1) // change opacity back for every node
          .select("circle")    // select the circle to alter its color
          .style("fill", function(d) { return color(d.group); });
          
      // If "All" isn't selected, filter for the selected value:
      if(value != "All") {
        node.filter(function(d) { return d.kontext != value; })
            .style("opacity", 0.5) // Change the opacity of text and circle for filtered items
            .select("circle")      // select the circle to alter its color
            .style("fill","#aaa");
      }
    })
    /* todo: add styles */
    .vertical-grid{
        stroke:#ccc;
        
      }
      
      .ordinate-text{
        font-size:10px;
        transform:translateY(10px);
      }
      
      div.tooltip {
        position: absolute;
        text-align: center;
        width: auto;
        height: auto;
        padding: 2px;
        font: 12px sans-serif;
        background: lightsteelblue;
        border: 0px;
        border-radius: 8px;
        pointer-events: none;
        opacity:0;
        padding:5px;
      }
      
      .right-align{
        position:absolute;
        right:100px;
        
      }
      .box,
      .label{
          display:inline-block;
      }
      
      .box{
        width:10px;
        height:10px;
        margin:0px 10px;
      }
    <!DOCTYPE html>
    
        <head>
    
            <meta charset = "utf-8">
            <link rel="stylesheet" type="text/css" href="style.css">
           
            <title>Ideal iDEP on D3.js</title>
            
       </head>
    
    
       <body>
          <!-- Kontext Option Button -->
          <select>
            <option value="Jira">01 - Jira</option>
            <option value="Ivis">02 - Ivis</option>
            <option value="All" selected>Whatever</option>
          </select>
          
          <!-- SVG as a canvas area -->
          <svg width="500" height="300"></svg>
          <!--<svg id="canvas" width="100%" height="100%"></svg> -->
          <!-- import d3.js library -->
          <script src="https://d3js.org/d3.v4.js"></script> 
          <!-- where the magic is happening -->    
          <script type="" src="appv4.js"></script>
    
       </body>
    
    </html>

    如果节点可以是多个上下文的一部分:

    {id: "0002", name: "name1", kontext: ["ContextA"], group: 2},
    {id: "0003", name: "name2", kontext: ["ContextA","ContextB"] , group: 2},
    

    您需要检查所选上下文是否在 kontext 数组中,如果所有 kontext 属性都是数组,而不是某些字符串和数组,这也会更容易。如果 kontext 是一个数组,你会有类似的东西:

     node.filter(function(d) { return d.kontext.indexOf(value) == -1; })
    

    【讨论】:

      猜你喜欢
      • 2016-12-24
      • 2017-01-30
      • 2015-08-03
      • 1970-01-01
      • 2013-03-04
      • 2012-09-20
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多