SVG defs 封装

Posted

技术标签:

【中文标题】SVG defs 封装【英文标题】:Svg defs encapsulation 【发布时间】:2018-07-06 14:52:24 【问题描述】:

我正在尝试在 React 组件中封装一个带有箭头的 SVG 行,而在 React 组件中没有任何全局 id,(但问题本身与 React 无关)。

例如小提琴https://jsfiddle.net/wzyzqhgh/1/

const LinkComponent = ( x1, y1, x2, y2, color ) => 
  const coordinates = calculateCoordinates(x1, y1, x2, y2)
  const linkStyle = calculateStyles(x1, y1, x2, y2)
  return (<svg style=linkStyle shapeRendering="geometricPrecision">
    <defs>
      <marker 
        id="arrow" 
        markerWidth=10 
        markerHeight=10 
        refX=9 
        refY=3 
        orient="auto" 
        markerUnits="strokeWidth"
      >
        <path d="M0,0 L0,6 L9,3 z" fill=color />
      </marker>
    </defs>
    <line
      x1=coordinates.x1
      y1=coordinates.y1
      x2=coordinates.x2
      y2=coordinates.y2
      strokeWidth=1
      stroke=color
      markerEnd="url(#arrow)"
    />
  </svg>)

这个组件在每次渲染时都会在本地定义一个marker,但似乎markerid 是全局的。所以当我这样做时:

ReactDom.render(
  (<div>
    <LinkComponent x1=10 y1=20 x2=100 y2=200 color="red" />
    <LinkComponent x1=10 y1=200 x2=200 y2=10 color="blue" />
  </div>),
  document.getElementById('test')
)

第一种颜色用于两个组件marker-end

问题:如何将markers 封装在单个svg 元素中,以免它们泄漏?除了id,还有其他方法可以在marker-* 属性中引用它们吗?如果不可以,不使用defs/markers如何实现类似的效果

【问题讨论】:

你没有。它只是 id 并且 id 是全局的。我想你可以单独绘制所有标记线。 【参考方案1】:

你有几个选择:

    将标记定义拉出到所有 LinkComponents 都引用的静态 SVG 中,或者

    每次生成一个随机的、唯一的id

    将颜色添加到 id,因此即使您有重复的标记定义,引用哪一个也没关系:

    id="arrow-color"
    

    不要使用标记。自己画箭头。

【讨论】:

添加颜色是一个不错的选择!你有关于如何在没有标记的情况下单独绘制箭头的资源吗?我首先使用标记的唯一原因是因为我不想自己计算线的角度并旋转箭头(三角形)。 看这个问答:***.com/questions/41737478/block-arrow-using-svg/…

以上是关于SVG defs 封装的主要内容,如果未能解决你的问题,请参考以下文章

vite vue引入svg图标及封装 (轻松上手)

在Vue中使用svg图标即封装自定义svg-icon标签

vue中封装svg-icon组件并使用

vue中使用svg-icon封装的组件来引用iconfont

vue中封装svg-icon组件并使用

封装redis