如何在 svg 中获取标记结束位置?

Ash*_*mar 3 javascript css svg

下面是您可以运行并查看输出的代码,该输出是一条黑色线条,在其结束位置带有一个标记。

<svg width="600px" height="200px">
  <defs>
    <marker id="arrow" markerWidth="10" markerHeight="10" refx="0" refy="3" orient="auto" markerUnits="strokeWidth">
      <path d="M0,0 L0,6 L9,3 z" fill="#000" />
    </marker>
  </defs>

  <line x1="50" y1="50" x2="250" y2="150" stroke="#000" stroke-width="5" marker-end="url(#arrow)" />
</svg>
Run Code Online (Sandbox Code Playgroud)

我想知道是否可以计算下图所示的标记结束位置的值在此处输入图片说明用红色箭头指向的红色圆圈?是否可以在数学上计算标记末端的位置?

Elf*_*yer 5

您唯一需要做的就是使用以下公式来获得红色圆圈的正确位置(即箭头的终点):

this.point.x = r * Math.cos(rad) + this.line.endX;
this.point.y = r * Math.sin(rad) + this.line.endY;
Run Code Online (Sandbox Code Playgroud)

基本上对于位置 x:

posX = arrowSizeX[width of the arrow * line stroke width] * Math.cos(rad)[rad = angle of the line in radian] + lineEndX[Position of the starting point of the arrow]

完整代码如下:JSFiddle

this.point.x = r * Math.cos(rad) + this.line.endX;
this.point.y = r * Math.sin(rad) + this.line.endY;
Run Code Online (Sandbox Code Playgroud)
var vue = new Vue({
  el: '#container',
  data: {
    svg: {
      width: 400,
      height: 200
    },
    line: {
      startX: 50,
      startY: 50,
      endX: 250,
      endY: 150
    },
    point: {
      x: 0,
      y: 0
    },
    arrow: {
      sizeX: 9,
      sizeY: 6
    },
    strokeWidth: 5
  },
  ready: function() {
    this.calculatePosition();
  },
  methods: {
    calculatePosition: function() {
      // Calculate the angle of the arrow in radian
      var rad = Math.atan2(this.line.endY - this.line.startY, this.line.endX - this.line.startX);

      // Calculate the radius (the length of the arrow)
      // Note: Your arrow size depends on the the 'strokeWidth' attribute of your line
      var r = this.arrow.sizeX * this.strokeWidth;

      // Calculate the position of the point
      this.point.x = r * Math.cos(rad) + this.line.endX;
      this.point.y = r * Math.sin(rad) + this.line.endY;
    }
  }
});

vue.$watch('arrow.sizeX', vue.calculatePosition);
vue.$watch('arrow.sizeY', vue.calculatePosition);
vue.$watch('line.startX', vue.calculatePosition);
vue.$watch('line.startY', vue.calculatePosition);
vue.$watch('line.endX', vue.calculatePosition);
vue.$watch('line.endY', vue.calculatePosition);
vue.$watch('strokeWidth', vue.calculatePosition);
Run Code Online (Sandbox Code Playgroud)
input,
label,
button {
  display: block;
}
#toolbar {
  display: inline-block;
  width: 150px;
}
Run Code Online (Sandbox Code Playgroud)