Modifying SVG path opacity and it's marker

2020-07-06 03:05发布

问题:

I'm trying to make some modifications to a path, defined using D3 programmatically. The change I want to make is quite simple, modifying the opacity of the path. The problem I've got is while the path itself will change, the end marker does not, and I'm not quite sure how to make it do so.

The marker is defined as so:

    // define arrow markers for graph links
    svg.append('svg:defs').append('svg:marker')
        .attr('id', 'end-arrow')
        .attr('viewBox', '0 -5 10 10')
        .attr('refX', 6)
        .attr('markerWidth', 3)
        .attr('markerHeight', 3)
        .attr('orient', 'auto')
        .append('svg:path')
            .attr('d', 'M0,-5L10,0L0,5')
            .attr('fill', '#CCCCCC');

The path:

        // Create the links between the nodes
    var links = svg.append("g")
                    .selectAll(".link")
                    .data(data.links)
                    .enter()
                    .append("path")
                        .attr("class", "link")
                        .attr("d", sankey.link())
                        .style('marker-end', "url(#end-arrow)")
                        .style("stroke-width", function (d) { return Math.max(1, d.dy); })
                        .sort(function (a, b) { return b.dy - a.dy; });

The code that I use to change the paths, which doesn't update the markers:

d3.selectAll("path.link")
      .filter(function (link) {
          // Find all the links that come to/from this node
          if (self.sourceLinksMatch(self, link, node)) {
              return true;
          }

          if (self.targetLinksMatch(self, link, node)) {
              return true;
          }

          return false;
      })
     .transition()
     .style("stroke-opacity", 0.5);

Can anyone suggest what I might need to change to modify the marker-end style too?

回答1:

Modifying the opacity instead of the stroke-opacity works.. so

d3.selectAll("path.link")
  .transition()
  .style("stroke-opacity", 0.5);

becomes

d3.selectAll("path.link")
  .transition()
  .style("opacity", 0.5);


回答2:

You should be able to do the same for the marker path definition:

d3.selectAll("marker path")
  .transition()
  .style("stroke-opacity", 0.5);


回答3:

You can set define preset names for your arrow markers

// build the arrow.
svg.append("svg:defs").selectAll("marker")
    .data(["HELPS","HELPED_BY","DAMAGES","REPELS","FAMILY", "KINGDOM"])      // Different link/path types can be defined here
  .enter().append("svg:marker")    // This section adds in the arrows
    .attr("id", String)
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)
    .attr("refY", -1.5)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
  .append("svg:path")
    .attr("d", "M0,-5L10,0L0,5");

// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
    .data(force.links())
  .enter().append("svg:path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type +")"; });

And configure their respective styles with CSS

marker#HELPS{fill:green;}
path.link.HELPS {
  stroke: green;
}

marker#HELPED_BY{fill:#73d216;}
path.link.HELPED_BY {
  stroke: #73d216;
}

marker#DAMAGES{fill:red;}
path.link.DAMAGES {
  stroke: red;
}


标签: svg d3.js