vislite
Version:
灵活、快速、简单的数据可视化交互式跨端前端库
214 lines (188 loc) • 6.49 kB
text/typescript
import type SVGConfigType from "../../../types/SVGConfig"
import { setAttribute } from "./tool"
import setStyle from "../setStyle"
import arc from "../canvas/arc"
import { toNode } from "./tool"
export const initDefs = (el: SVGElement) => {
const defs = el.getElementsByTagName('defs')
if (defs.length <= 0) {
const newDefs = toNode("defs")
el.appendChild(newDefs)
return newDefs
} else {
return defs[0]
}
}
// 文字统一设置方法
export const initText = (
el: SVGElement,
config: SVGConfigType,
x: number,
y: number,
deg: number
) => {
if (el.nodeName.toLowerCase() !== "text") throw new Error("Need a <text> !")
// 垂直对齐采用dy实现
setAttribute(
el,
"dy",
({
top: (config["fontSize"] as number) * 0.5,
middle: 0,
bottom: -(config["fontSize"] as number) * 0.5,
} as {
[key: string]: number
})[config.textBaseline as string]
)
setStyle(el, {
// 文字对齐方式
"text-anchor": ({
left: "start",
right: "end",
center: "middle",
} as {
[key: string]: string
})[config.textAlign as string],
"dominant-baseline": "central",
// 文字大小和字体设置
"font-size": config["fontSize"] + "px",
"font-family": config["fontFamily"],
})
// 位置
setAttribute(el, "x", x)
setAttribute(el, "y", y)
// 旋转
if (typeof deg == "number") {
deg = deg % 360
setAttribute(el, "transform", "rotate(" + deg + "," + x + "," + y + ")")
}
}
// 画圆统一设置方法
export const initCircle = (el: SVGElement, cx: number, cy: number, r: number) => {
if (el.nodeName.toLowerCase() !== "circle")
throw new Error("Need a <circle> !")
setAttribute(el, "cx", cx)
setAttribute(el, "cy", cy)
setAttribute(el, "r", r)
}
// 路径统一设置方法
export const initPath = (el: SVGElement, path: string) => {
if (el.nodeName.toLowerCase() !== "path") throw new Error("Need a <path> !")
setAttribute(el, "d", path)
}
// 画矩形统一设置方法
export const initRect = (
el: SVGElement,
config: SVGConfigType,
x: number,
y: number,
width: number,
height: number
) => {
if (el.nodeName.toLowerCase() !== "path") throw new Error("Need a <path> !")
const rectRadius: Array<number> = [];
if (Array.isArray(config.rectRadius) && config.rectRadius.length > 0) {
for (let index = 0; index < 4; index++) {
rectRadius.push(...config.rectRadius)
}
}
// 由于高和宽不可以是负数,校对一下
if (height < 0) {
height *= -1
y -= height
}
if (width < 0) {
width *= -1
x -= width
}
let d = ""
if (rectRadius.length >= 4) {
d = "M" + (x + rectRadius[0]) + " " + y
d += "L" + (x + width - rectRadius[1]) + " " + y
d += "A" + rectRadius[1] + " " + rectRadius[1] + " 0 0 1 " + (x + width) + " " + (y + rectRadius[1])
d += "L" + (x + width) + " " + (y + height - rectRadius[2])
d += "A" + rectRadius[2] + " " + rectRadius[2] + " 0 0 1 " + (x + width - rectRadius[2]) + " " + (y + height)
d += "L" + (x + rectRadius[3]) + " " + (y + height)
d += "A" + rectRadius[3] + " " + rectRadius[3] + " 0 0 1 " + x + " " + (y + height - rectRadius[3])
d += "L" + x + " " + (y + rectRadius[0])
d += "A" + rectRadius[0] + " " + rectRadius[0] + " 0 0 1 " + (x + rectRadius[0]) + " " + y
} else {
d = "M" + x + " " + y
d += "L" + (x + width) + " " + y
d += "L" + (x + width) + " " + (y + height)
d += "L" + x + " " + (y + height)
d += "Z"
}
setAttribute(el, "d", d)
}
// 画弧统一设置方法
export const initArc = (
el: SVGElement,
config: SVGConfigType,
cx: number,
cy: number,
r1: number,
r2: number,
beginDeg: number,
deg: number
) => {
if (el.nodeName.toLowerCase() !== "path") throw new Error("Need a <path> !")
beginDeg = (beginDeg / 180) * Math.PI
deg = (deg / 180) * Math.PI
beginDeg = beginDeg % (Math.PI * 2)
if (r1 > r2) {
const temp = r1
r1 = r2
r2 = temp
}
// 当|deg|>=2π的时候都认为是一个圆环
if (deg >= Math.PI * 1.999999 || deg <= -Math.PI * 1.999999) {
deg = Math.PI * 1.999999
} else {
deg = deg % (Math.PI * 2)
}
arc(
beginDeg,
deg,
cx,
cy,
r1,
r2,
function (
beginA: number,
endA: number,
begInnerX: number,
begInnerY: number,
begOuterX: number,
begOuterY: number,
endInnerX: number,
endInnerY: number,
endOuterX: number,
endOuterY: number,
r: number
) {
const f = endA - beginA > Math.PI ? 1 : 0
let d = "M" + begInnerX + " " + begInnerY
if (r < 0) r = -r
d +=
// 横半径 竖半径 x轴偏移角度 0小弧/1大弧 0逆时针/1顺时针 终点x 终点y
"A" + r1 + " " + r1 + " 0 " + f + " 1 " + endInnerX + " " + endInnerY
// 结尾
if (config.arcEndCap == "round")
d += "A" + r + " " + r + " " + " 0 1 0 " + endOuterX + " " + endOuterY
else if (config.arcEndCap == "-round")
d += "A" + r + " " + r + " " + " 0 1 1 " + endOuterX + " " + endOuterY
else d += "L" + endOuterX + " " + endOuterY
d +=
"A" + r2 + " " + r2 + " 0 " + f + " 0 " + begOuterX + " " + begOuterY
// 开头
if (config.arcStartCap == "round")
d += "A" + r + " " + r + " " + " 0 1 0 " + begInnerX + " " + begInnerY
else if (config.arcStartCap == "-round")
d += "A" + r + " " + r + " " + " 0 1 1 " + begInnerX + " " + begInnerY
else d += "L" + begInnerX + " " + begInnerY
if (config.arcStartCap == "butt") d += "Z"
setAttribute(el, "d", d)
}
)
}