How to set the direction of the arrowhead?

2019-06-08 20:28发布

This refers to my previous question: How to draw line automatically by reading coordinates from file?

I need to add an arrow head at one side, based on one column flag (R for right, L for left):

x1,y1,x2,y2,Flag
1,2,3,2,L
3,3,5,3,R 
5,3,6,3,L 
7,5,7,5,R
8,6,8,6,L 
9,7,2,7,L

How is it possible?

1条回答
叛逆
2楼-- · 2019-06-08 21:17

The most obvious solution here would be setting the marker as marker-end or marker-start according to the value of the flag property.

However, on a second thought, we can do something more interesting here: we can set all markers as marker-end and, according to the flag, we swap the x1 and x2 properties, making:

  • x1 smaller than x2 if flag is R;
  • x1 bigger than x2 if flag is L;

It can be done with:

data.forEach(function(d) {
  if ((d.flag === "L" && d.x1 < d.x2) || (d.flag === "R" && d.x1 > d.x2)) {
    d.x1 = d.x2 + (d.x2 = d.x1, 0);
  }
});

Here is the demo:

const csv = `x1,y1,x2,y2,flag
1,2,3,2,L
3,3,5,4,R
5,3,6,3,L
7,5,8,5,R
8,6,9,6,L
9,7,2,8,L`;

const data = d3.csvParse(csv, function(d) {
  d.x1 = +d.x1 * 20;
  d.y1 = +d.y1 * 15;
  d.x2 = +d.x2 * 20;
  d.y2 = +d.y2 * 15;
  return d;
});

data.forEach(function(d) {
  if ((d.flag === "L" && d.x1 < d.x2) || (d.flag === "R" && d.x1 > d.x2)) d.x1 = d.x2 + (d.x2 = d.x1, 0);
});

const svg = d3.select("svg");

const marker = svg.append("defs")
  .append("marker")
  .attr("id", "marker")
  .attr("viewBox", "0 0 10 10")
  .attr("refX", "5")
  .attr("refY", "5")
  .attr("markerWidth", "6")
  .attr("markerHeight", "6")
  .attr("orient", "auto")
  .append("path")
  .attr("d", "M 0 0 L 10 5 L 0 10 z");

const enterSelection = svg.selectAll(null)
  .data(data)
  .enter()
  .append("line")
  .attr("x1", d => d.x1)
  .attr("y1", d => d.y1)
  .attr("x2", d => d.x2)
  .attr("y2", d => d.y2)
  .attr("marker-end", "url(#marker)")
  .style("stroke-width", "1px")
  .style("stroke", "black");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

Since your values are too small I'm multiplying them here, so we can better see the lines. Also, because you didn't share any marker, I'm using the one at MDN.

查看更多
登录 后发表回答