带标记的Javascript动态SVG

时间:2019-01-23 18:56:42

标签: javascript svg

我有一些JavaScript,这些JavaScript会在某些数据之上生成SVG路径,以显示工作进度。我的线条可以显示一个框与另一个框之间的连接,但是我无法添加标记箭头。

我通过使用以下结构来引用箭头:

<svg id="svg1" width="0" height="0">
  <defs>
      <marker id="Triangle" viewBox="0 0 10 10" refX="1" refY="5" 
              markerUnits="strokeWidth" markerWidth="4" markerHeight="3"
              orient="auto">
        <path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"/>
      </marker>
    </defs>
    <path id="path1" class="path" marker-end="url(#Triangle)" fill="none" stroke-width="10"/>
</svg>

问题在于,它无法正确生成三角形,并且几乎看起来像是一个截止正方形?三角形应位于右下角,因为路径将顶盒连接到了底盒。

enter image description here

JS小提琴:

http://jsfiddle.net/qLhunt7k/

关于为什么它看起来不像我期望的三角形的任何想法吗?

1 个答案:

答案 0 :(得分:3)

您的问题是由多种因素引起的:

  1. 标记位于SVG底部,因为您的行在SVG底部结束。标记的偏移量(refXrefY)在箭头的底部。因此绘制标记,以便将其底部(最宽的部分)放置在线条结束的位置。因此,您只能看到它的顶部像素。

  2. 通过在SVG上设置overflow: visible,可以防止剪切,并使标记可见。但是,您还必须对#svgContainer容器div进行同样的操作。

    #svgContainer {
      ...
      overflow: visible;
    }
    
    #svgContainer svg {
      overflow: visible;
    }
    

    另一种选择是不要一直画线到最底端。这样您就可以在底部留出空间来绘制标记。例如。将路径生成器更改为:

    " V" + (endY-30));
    

    我在这里使用了30,因为它与stroke-width中的0.7em相匹配。我建议更改CSS以将px的值使用stroke-width。否则,将来更改字体大小可能会再次破坏标记。

    如果选择此方法,则在计算SVG宽度时,还需要为标记留出水平空间。例如:

    if (svg.getAttribute("width") < (endX + stroke * 3))
       svg.setAttribute("width", (endX + stroke * 3));
    
  3. 接下来,path {}规则引起了问题。 path的一般定义将覆盖标记定义中的fill="context-stroke"属性。这导致标记具有较大的笔触,这又使标记边界溢出并使其看起来像矩形。解决方法是摆脱path {}样式。

    path {
    }
    
  4. 最后剩下的问题是fill="context-stroke"。这是新的SVG2,尚不被很好地支持。例如,它可以在Chrome上运行,但似乎还不能在Firefox上运行。因此,现在,我建议仅在标记定义中使用普通填充。

    <marker id="Triangle" viewBox="0 0 10 10" refX="0" refY="5" 
            markerUnits="strokeWidth" markerWidth="4" markerHeight="3"
            orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" fill="#000"/>
    </marker>
    

提琴:http://jsfiddle.net/ptLc1gyx/