svg的学习

159 阅读2分钟

SVG 的全称是 Scalable Vector Graphics,可缩放矢量图,它是浏览器支持的一种基于 XML 语法的图像格式,SVG 属于声明式绘图系统。

有效的命名空间URI(此命名空间用于标识该节点属于哪种XML类型)

HTML: www.w3.org/1999/xhtml SVG:www.w3.org/2000/svg XBL:www.mozilla.org/xbl XUL:www.mozilla.org/keymaster/g… 一个xml文档可能包含多个软件模块的元素和属性,在不同软件模块中使用相同名称的元素或属性,可能会导致识别和冲突问题,而xml命名空间可以解决该问题。

注意:svg标签的viewBox属性在未设置的时候默认和画布大小(由svg的宽高属性值决定)等同,如果设置了,那么在展示的时候,就会等比缩放,eg:svg的画布大小为200*200,而viewBox的值为“0 0 100 100”则表示在展示的时候会是正常像素的两倍
1、SVG 绘制可视化图表
html部分
<h1 id="title"></h1>
<svg xmlns="http://www.w3.org/2000/svg" class="svg" version="1.1"></svg>
js部分
//初始化数据
initRelation () {
      const baseData = await (await fetch('https://s5.ssl.qhres2.com/static/b0695e2dd30daa64.json')).json()
      // 将数组内的一级叶子节点全部提取出来作为一个数组
      const regions = d3.hierarchy(baseData).sum(d => 1).sort((a, b) => { return b.value - a.value })
      const pack = d3.pack().size([400, 300]).padding(1)
      const root = pack(regions)
      const svg = document.querySelector('.svg')
      createSvg(svg, root)
}
//创建xml基本结构
createSvg (dom, node, fillStyle = 'rgba(0, 0, 0, 0.2)', textColor = 'white') {
     const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
     const { x, y, r } = node
     circle.setAttribute('cx', x)
     circle.setAttribute('cy', y)
     circle.setAttribute('r', r)
     circle.setAttribute('data-name', node.data.name)
     circle.setAttribute('fill', fillStyle)
     dom.appendChild(circle)
    if (node.children) {
        const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
        node.children.forEach((item, index) => {
          this.createSvg(g, item)
        })
        dom.appendChild(g)
      } else {
        const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
        text.setAttribute('fill', textColor)
        text.setAttribute('font-family', 'Arial')
        text.setAttribute('font-size', '0.05rem')
        text.setAttribute('text-anchor', 'middle')
        text.setAttribute('x', x)
        text.setAttribute('y', y)
        text.textContent = node.data.name
        dom.appendChild(text)
      }
}

// 使用svg绘制结构层次关系图
drawOfSvg () {
      const svg = document.querySelector('.svg')
      const title = document.getElementById('title')
      let preDom = null
      svg.addEventListener('mousemove', (e) => {
        let target = e.target
        if (target.nodeName === 'text') {
          target = target.previousElementSibling
        }
        const childName = target.getAttribute('data-name')
        let parentName = null
        if (target.parentNode) {
          parentName = target.parentNode.previousElementSibling.getAttribute('data-name')
        }
        title.textContent = parentName ? parentName + '-' + childName : childName
        if (preDom !== target) {
          if (preDom) {
            preDom.setAttribute('fill', 'rgba(134, 187, 255, .4)')
          }
        }
        target.setAttribute('fill', 'rgba(0, 0, 0, 0.2)')
        preDom = target
      })
      createSvg(svg, this.root)
},
处理后的数据结构
{
  "name":"中国",
  "children":
  [
    { 
      "name":"浙江" , 
        "children":
        [
            {"name":"杭州" },
            {"name":"宁波" },
            {"name":"温州" },
            {"name":"绍兴" }
        ] 
      },
    { 
      "name":"广西" , 
      "children":
      [
        {"name":"桂林"},
        {"name":"南宁"},
        ...
    }
  ]
}
实现效果图

image

注意:

xml语法的结构和html并不相同,并非是html那种层次结构清晰的节点关系,xml语法越是内部的元素越是在结构的后面展示,而非里面