2023年1月18日
By: Chase

svg初步学习

目标

实现下图: 其中起点和终点, 都是一个绝对定位的div, 本文主要详解svg的绘制.

起点
终点

绘svg

动手前所需了解的svg知识

名称解释
svg基于xml的标记语言, 在此实例中可以当做html的基础element(p, div等)理解, property(className, style等)基本同dom, css实现有区别, svg规范规定这些可用css设置
xmlnsxml的namespace, 避免element命名冲突
pathsvg的element, 就是我们实例中的线
defs用于存储以后要使用的图形对象
dpath的形状属性
MMove to, 起始落笔的地方, 后面跟的x, y是相对于父级包裹的svg坐标
LLine to, 绘制到某为止, 后面跟x, y是相对于父级包裹的svg坐标
V, HH,绘制水平线; V,绘制垂直线, 都只接一个距离参数
Z终点到起始的闭合
fill理解成css中的background-color
stroke理解成css中的color

配合代码讲解图中折线

demo中的svg折线代码

    <svg
        xmlns="http://www.w3.org/2000/svg"
        style="
            position: absolute;
            left: 40px;
            top: 50px;
        "
    >
        // 这一块是折线
        <path
            d=" M 0 0 
                L 0 50
                L 100 50
                L 100 100"
            fill="none"
            stroke="blue" 
        />
        // 这一块是箭头
        <path
            d="
                M 100 100 
                L 95 95
                L 105 95
                Z 
            "
            fill="blue"
            xmlns="http://www.w3.org/2000/svg"
        />
    </svg>

配合下面的图:

  1. svg的绝对定位, 给整体折线定了一个{left: 40, top: 50}绝对定位的偏移量
  2. M起点, 是坐标系0,0
  3. 每一个坐标对应画的直线

图-0

动态获得svg的各个位置

获取起始终点的一些坐标

定义一个函数, 获取特定id元素的绝对定位偏移量, 代码比较易懂, 如下:

function getMid() {
    const targetDom = document.getElementById(id)

    const {
        offsetHeight: height,
        offsetLeft: left,
        offsetTop: top,
        offsetWidth: width
    } = targetDom

    return {
        topMid: {
            x: left + (width / 2),
            y: top
        },
        bottomMid: {
            x: left + (width / 2),
            y: top + height
        }
    }
}

引申讲解offsetLeft, offsetTop: 同position: absolute定位下的top, left, 即相对于最近的非static定位(一般设relative)parent元素的偏移.

svg的起点与拐点计算

略. 起点终点元素的长宽, 坐标位置, 都能拿到, 各个点的坐标. 就是一些简单的数学计算了. 只要你的包裹层绝对定位坐标系构建的很清晰.

动态创建svg元素

// 创建svgDom
// 此处注意, 不能用createElement
const svgDom = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
// 创建连线path
const lineDom = document.createElementNS('http://www.w3.org/2000/svg', 'path')

lineDom.setAttribute(
    'd',
    `M ${点1.X} 0
    L ${点2.X} ${点2.Y}
    L ${点3.X} ${点3.Y}
    L ${点4.X} ${点4.Y}`
)

// 插入dom
svgDom.append(lineDom)

document.getElementById(containerId).append(svgDom)
Tags: 前端 svg