用javascript画一个Atom官网的SVG图标

717 阅读2分钟

用javascript画一个Atom官网的SVG图标

image.png

关键属性和元素

  • svg viewBox: 属性的值是一个包含4个参数的列表 min-x, min-y, width and height, 以空格或者逗号分隔开, 在用户空间中指定一个矩形区域映射到给定的元素。

定义一个显示区域、比例(svg缩放应该保持纵横比),对外(父级以上设置width,height)值=值,对内和子元素的是 值:值 的比例关系。svg设置的宽高都会相应的根据比例(值:值)显示子元素大小和位置。

  • circle stroke-width: 圆环宽度,边框会有一半宽度算在宽高里(和半径重合)。宽度=半径 * 2 + 圆环宽度;如下图填充的圆和半透明圆环块:
<svg viewBox="0 0 100 100">
    <circle cx="50" cy="50" r="44" stroke-width="12" stroke-dasharray="10" fill="#ffffff00" stroke="#ffffff33"></circle>
    <circle cx="50" cy="50" r="44" fill="#ffffff33"></circle>
</svg>

image.png

  • circle stroke-dasharray: 它是一个lengthpercentage数列,数与数之间用逗号或者空白隔开,指定短划线和缺口的长度。如果提供了奇数个值,则这个值的数列重复一次,从而变成偶数个值。这个值对应的是每一段的宽度和空白宽度。
  • <animateTransform>: 关键元素,可以控制svg动画,repeatCount设置为“indefinite”的时候无限循环。支持transform的很多属性。(但是貌似很坑的旋转中心需要用css transform-origin: center处理)

然后就是一顿画圆,画不同颜色和不同半径的圆就OK

  • 创建命名空间下的节点。

由于document.createElement创建的是html下的普通元素,所以,我们创建svg图标还需要用到 document.createElementNS

let element = document.createElementNS(namespaceURI, qualifiedName[, options]);

有效的namespaceURI

  • HTML - 参阅 http://www.w3.org/1999/xhtml
  • SVG - 参阅 http://www.w3.org/2000/svg
  • XBL - 参阅 http://www.mozilla.org/xbl
  • XUL - 参阅 http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul

其他都好说,直接上源码:

function mount(selector, circles) {
  const svgNS = "http://www.w3.org/2000/svg"
  const content = document.querySelector(selector)
​
  const svg = document.createElementNS(svgNS, "svg")
  svg.setAttribute("viewBox", "0 0 100 100")
  content.innerHTML = ""
​
  const group = document.createElementNS(svgNS, "g")
  group.style.transformOrigin = "center"
  const animationTransform = document.createElementNS(svgNS, "animateTransform")
  animationTransform.setAttribute("attributeName", "transform");
  animationTransform.setAttribute("attributeType", "XML")
  animationTransform.setAttribute("type", "rotate")
  animationTransform.setAttribute("to", "360")
  animationTransform.setAttribute("repeatCount", "indefinite")
​
  circles.forEach(circle => {
    const _group = group.cloneNode(true)
    const _animationTransform = animationTransform.cloneNode(true)
    const child = document.createElementNS(svgNS, 'circle')
    child.setAttribute("cx", "50")
    child.setAttribute("cy", "50")
    child.setAttribute("r", circle.r)
    child.setAttribute("fill", "#ffffff00")
    child.setAttribute("stroke-width", circle.width)
    child.setAttribute("stroke-dasharray", (circle.dashArray || [10, 25]).join(","))
    child.setAttribute("stroke", circle.color)
​
    _animationTransform.setAttribute("from", circle.offset || "0")
    if (circle.speed) _animationTransform.setAttribute("dur", circle.speed + "s")
    _group.appendChild(child)
    _group.appendChild(_animationTransform)
    svg.appendChild(_group)
  })
​
  content.appendChild(svg)
}
​

可以上CodePen 体验和获取代码。一毛一样打在评论区。

参考资料
走进HTML5-让你从不懂到精通SVG(大量实例操作) - 掘金 (juejin.cn)
SVG入门—如何手写SVG - 掘金 (juejin.cn)
SVG:理解stroke-dasharray和stroke-dashoffset属性 - 掘金 (juejin.cn)

(知乎文章同步发布)