二维Svg转矢量 不支持Svg2.0
import { ElMessage } from 'element-plus'
import { parse } from 'svgson'
import JsonToView from './view' const TAU = Math.PI * 2
let StyleClasse = '' const mapToEllipse = ({ x, y }, rx, ry, cosphi, sinphi, centerx, centery) => {
x *= rx
y *= ry const xp = cosphi * x - sinphi * y
const yp = sinphi * x + cosphi * y return {
x: xp + centerx,
y: yp + centery
}
} const approxUnitArc = (ang1, ang2) => {
// If 90 degree circular arc, use a constant
// as derived from http://spencermortensen.com/articles/bezier-circle
const a =
ang2 === 1.5707963267948966
? 0.551915024494
: ang2 === -1.5707963267948966
? -0.551915024494
: (4 / 3) * Math.tan(ang2 / 4) const x1 = Math.cos(ang1)
const y1 = Math.sin(ang1)
const x2 = Math.cos(ang1 + ang2)
const y2 = Math.sin(ang1 + ang2) return [
{
x: x1 - y1 * a,
y: y1 + x1 * a
},
{
x: x2 + y2 * a,
y: y2 - x2 * a
},
{
x: x2,
y: y2
}
]
} const vectorAngle = (ux, uy, vx, vy) => {
const sign = ux * vy - uy * vx < 0 ? -1 : 1 let dot = ux * vx + uy * vy if (dot > 1) {
dot = 1
} if (dot < -1) {
dot = -1
} return sign * Math.acos(dot)
} const getArcCenter = (
px,
py,
cx,
cy,
rx,
ry,
largeArcFlag,
sweepFlag,
sinphi,
cosphi,
pxp,
pyp
) => {
const rxsq = Math.pow(rx, 2)
const rysq = Math.pow(ry, 2)
const pxpsq = Math.pow(pxp, 2)
const pypsq = Math.pow(pyp, 2) let radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq if (radicant < 0) {
radicant = 0
} radicant /= rxsq * pypsq + rysq * pxpsq
radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1) const centerxp = ((radicant * rx) / ry) * pyp
const centeryp = ((radicant * -ry) / rx) * pxp const centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2
const centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2 const vx1 = (pxp - centerxp) / rx
const vy1 = (pyp - centeryp) / ry
const vx2 = (-pxp - centerxp) / rx
const vy2 = (-pyp - centeryp) / ry let ang1 = vectorAngle(1, 0, vx1, vy1)
let ang2 = vectorAngle(vx1, vy1, vx2, vy2) if (sweepFlag === 0 && ang2 > 0) {
ang2 -= TAU
} if (sweepFlag === 1 && ang2 < 0) {
ang2 += TAU
} return [centerx, centery, ang1, ang2]
} const arcToBezier = ({
px,
py,
cx,
cy,
rx,
ry,
xAxisRotation = 0,
largeArcFlag = 0,
sweepFlag = 0
}) => {
const curves: any = [] if (rx === 0 || ry === 0) {
return []
} const sinphi = Math.sin((xAxisRotation * TAU) / 360)
const cosphi = Math.cos((xAxisRotation * TAU) / 360) const pxp = (cosphi * (px - cx)) / 2 + (sinphi * (py - cy)) / 2
const pyp = (-sinphi * (px - cx)) / 2 + (cosphi * (py - cy)) / 2 if (pxp === 0 && pyp === 0) {
return []
} rx = Math.abs(rx)
ry = Math.abs(ry) const lambda =
Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2) if (lambda > 1) {
rx *= Math.sqrt(lambda)
ry *= Math.sqrt(lambda)
} let [centerx, centery, ang1, ang2] = getArcCenter(
px,
py,
cx,
cy,
rx,
ry,
largeArcFlag,
sweepFlag,
sinphi,
cosphi,
pxp,
pyp
) // If 'ang2' == 90.0000000001, then `ratio` will evaluate to
// 1.0000000001. This causes `segments` to be greater than one, which is an
// unecessary split, and adds extra points to the bezier curve. To alleviate
// this issue, we round to 1.0 when the ratio is close to 1.0.
let ratio = Math.abs(ang2) / (TAU / 4)
if (Math.abs(1.0 - ratio) < 0.0000001) {
ratio = 1.0
} const segments = Math.max(Math.ceil(ratio), 1) ang2 /= segments for (let i = 0; i < segments; i++) {
curves.push(approxUnitArc(ang1, ang2))
ang1 += ang2
} return curves.map(curve => {
const { x: x1, y: y1 } = mapToEllipse(
curve[0],
rx,
ry,
cosphi,
sinphi,
centerx,
centery
)
const { x: x2, y: y2 } = mapToEllipse(
curve[1],
rx,
ry,
cosphi,
sinphi,
centerx,
centery
)
const { x, y } = mapToEllipse(
curve[2],
rx,
ry,
cosphi,
sinphi,
centerx,
centery
) return { x1, y1, x2, y2, x, y }
})
} const SvgToShape = (oBJht, file = undefined, URL = undefined, callback: any = undefined) => { let refX = 0
let refY = 0
let scaleX: any = 1
let scaleY: any = 1
const set16ToRgb = str => {
var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
if (!reg.test(str)) {
return str
}
let newStr = str.toLowerCase().replace(/\#/g, '')
let len = newStr.length
if (len == 3) {
let t = ''
for (var i = 0; i < len; i++) {
t += newStr.slice(i, i + 1).concat(newStr.slice(i, i + 1))
}
newStr = t
}
let arr: any = [] //将字符串分隔,两个两个的分隔
for (var i = 0; i < 6; i = i + 2) {
let s = newStr.slice(i, i + 2)
arr.push(parseInt('0x' + s))
}
return 'rgb(' + arr.join(',') + ')'
} //hex -> rgba
const hexToRgba = (hex, opacity) => {
hex && hex.toLowerCase()
!hex && (hex = '#000')
if (hex === 'none') return undefined return rgbToRgba(set16ToRgb(hex), opacity)
}
const rgbToRgba = (color, alp = 1) => {
let rgbaAttr = color.match(/[\d.]+/g) if (rgbaAttr && rgbaAttr.length >= 3) {
let r, g, b
r = rgbaAttr[0]
g = rgbaAttr[1]
b = rgbaAttr[2]
return 'rgba(' + r + ',' + g + ',' + b + ',' + alp + ')'
}
return 'rgba(0,0,0,' + alp + ')'
} // X偏量
const X = value => {
const v = Number(value) || 0 return (v - refX) / (scaleX === undefined ? 1 : scaleX)
}
// Y偏量
const Y = value => {
const v = Number(value) || 0 return (v - refY) / (scaleY === undefined ? 1 : scaleY)
} const k: any = {
modified: new Date().toString(),
comps: [],
background: undefined,
width: 512,
height: 512
}
const trim = function (x) {
return x.replace(/^\s+|\s+$/g, '')
}
const compressSpaces = function (x) {
return x.replace(/[\s\r\t\n]+/gm, ' ')
} function Rect2path(x, y, width, height, rx, ry) {
/*
* rx 和 ry 的规则是:
* 1. 如果其中一个设置为 0 则圆角不生效
* 2. 如果有一个没有设置则取值为另一个
*/
rx = rx || ry || 0;
ry = ry || rx || 0;
//非数值单位计算,如当宽度像100%则移除
if (isNaN(x - y + width - height + rx - ry)) return;
rx = rx > width / 2 ? width / 2 : rx;
ry = ry > height / 2 ? height / 2 : ry;
//如果其中一个设置为 0 则圆角不生效
if (0 == rx || 0 == ry) {
// var path =
// 'M' + x + ' ' + y +
// 'H' + (x + width) + 不推荐用绝对路径,相对路径节省代码量
// 'V' + (y + height) +
// 'H' + x +
// 'z';
var path =
'M' + x + ' ' + y +
'h' + width +
'v' + height +
'h' + -width +
'z';
} else {
var path =
'M' + x + ' ' + (y + ry) +
'a' + rx + ' ' + ry + ' 0 0 1 ' + rx + ' ' + (-ry) +
'h' + (width - rx - rx) +
'a' + rx + ' ' + ry + ' 0 0 1 ' + rx + ' ' + ry +
'v' + (height - ry - ry) +
'a' + rx + ' ' + ry + ' 0 0 1 ' + (-rx) + ' ' + ry +
'h' + (rx + rx - width) +
'a' + rx + ' ' + ry + ' 0 0 1 ' + (-rx) + ' ' + (-ry) +
'z';
}
return path;
} const CreateDefalutShape = (comp, attributes) => {
let style = {} if (attributes)
for (const key in attributes) {
if (Object.prototype.hasOwnProperty.call(attributes, key)) {
const element = attributes[key]
style[key] = element
}
} if (attributes && attributes.style) {
const S = attributes.style
.replace(
/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm,
''
)
.replace(/[\s\r\t\n]+/gm, ' ')
.split(';')
S &&
S.forEach(ele => {
ele = trim(compressSpaces((ele || '').replace(/,/g, ' ')))
var sv = ele.split(':')
if (sv && sv.length === 2) style[sv[0]] = sv[1]
})
} if ('fill' in style)
comp.background =
hexToRgba(style['fill'], Number(style['fill-opacity'] === undefined ? 1 : style['fill-opacity'])) ||
undefined if ('stroke' in style)
comp.borderColor =
hexToRgba(style['stroke'], Number(style['stroke-opacity'] === undefined ? 1 : style['stroke-opacity'])) ||
undefined
if ('opacity' in style) comp.opacity = Number(style['opacity'])
if ('stroke-width' in style) comp.borderWidth =
style['stroke-width'] === undefined ? 1 : style['stroke-width'] if (attributes?.class) { function configobj(arr) {
const result = {}
if (arr && arr.length > 0) {
let currentKey = ""
let currentValue = ""
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
currentKey = arr[i].match(/([^:;]\S[^:;]+)(?=\:)/)[0]
currentValue = arr[i].match(/(?<=\:)([^:;]\S[^:;]+)/)[0]
}
result[currentKey] = currentValue
}
}
return result
}
var sls = StyleClasse.match(/(\w*?-\w*)\s+\{\s+(\w*)\:\s+.?\w*.?\s+\}/g) || StyleClasse.match(/(?<=\.).*?\}/g)
sls && sls.forEach(element => { var r = RegExp(".*" + attributes.class + ".*", "i"); if (r.test(element)) {
var val = element.substring(element.indexOf('{') + 1, element.length).replace(/}/g, '').replace(/\s/g, "").match(/([^;]\S[^;]+)\:([^;]\S[^;]+)/g)
var values = configobj(val)
if (values) { if ('fill' in values)
comp.background =
hexToRgba(values['fill'], Number(values['fill-opacity'] === undefined ? 1 : style['fill-opacity'])) ||
undefined if ('stroke' in values)
comp.borderColor =
hexToRgba(values['stroke'], Number(values['stroke-opacity'] === undefined ? 1 : style['stroke-opacity'])) ||
undefined
if ('opacity' in values) comp.opacity = Number(values['opacity']) } } }); } comp.pixelPerfect = true
return comp
} const parseText = (k, ele) => {
let style = {} if (ele.attributes)
for (const key in ele.attributes) {
if (Object.prototype.hasOwnProperty.call(ele.attributes, key)) {
const element = ele.attributes[key]
style[key] = element
}
} const fontsize = style['font-size'] === undefined ? 24 : style['font-size']
let txt = ''
if (ele.children)
ele.children.forEach(e => {
txt += e.value || ''
}) let text: any = CreateDefalutShape(
{
type: 'text',
rect: [
X(ele.attributes.x),
Y(ele.attributes.y),
(X(fontsize) * (txt.length === undefined ? 1 : txt.length)) / 2,
Y(fontsize)
],
text: txt,
color:
hexToRgba(
style['fill'] || '#000',
Number(style['fill-opacity'] === undefined ? 1 : style['fill-opacity'])
) || undefined,
font: style['font-size'] + ' ' + style['font-family']
},
undefined
)
if ('opacity' in style) text.opacity = Number(style['opacity']) // text.rotation = style['transform']
k.comps.push(text)
} // 多线段
const parsepolygon = (k, ele) => {
let style = {} if (ele.attributes)
for (const key in ele.attributes) {
if (Object.prototype.hasOwnProperty.call(ele.attributes, key)) {
const element = ele.attributes[key]
style[key] = element
}
}
let points: any = []
if (!style['points']) return const lpoint = style['points'].split(' ') let indexkey = 0
lpoint.forEach(e => {
const p = e.split(',')
if (p && p.length === 2) points.push(X(p[0])), points.push(Y(p[1])) if (p && p.length === 1) {
indexkey % 2 === 0 && points.push(X(p[0])),
indexkey % 2 !== 0 && points.push(Y(p[0])),
indexkey++
}
}) let text: any = CreateDefalutShape(
{
type: 'shape',
points: points
},
undefined
)
if ('fill' in style)
text.background =
hexToRgba(style['fill'], Number(style['fill-opacity'] === undefined ? 1 : style['fill-opacity'])) ||
undefined
if ('stroke-linejoin' in style) text.borderJoin = style['stroke-linejoin']
if ('stroke-linecap' in style) text.orderCap = style['stroke-linecap']
if ('stroke' in style)
text.borderColor =
hexToRgba(style['stroke'], Number(style['stroke-opacity'] === undefined ? 1 : style['stroke-opacity'])) ||
undefined
if ('opacity' in style) text.opacity = Number(style['opacity'])
text.borderWidth =
style['stroke-width'] === undefined ? 1 : style['stroke-width']
k.comps.push(text)
} const parseImage = (k, ele) => {
let style = {} if (ele.attributes)
for (const key in ele.attributes) {
if (Object.prototype.hasOwnProperty.call(ele.attributes, key)) {
const element = ele.attributes[key]
style[key] = element
}
} let text: any = CreateDefalutShape(
{
type: 'image',
rect: [
X(ele.attributes.x),
Y(ele.attributes.y),
X(style['width']),
Y(style['height'])
],
name: style['href']
},
undefined
)
if ('opacity' in style) text.opacity = Number(style['opacity'])
if (
ele.attributes.x !== undefined &&
ele.attributes.y !== undefined &&
style['width'] !== undefined &&
style['height'] !== undefined &&
style['href']
)
k.comps.push(text)
} // 添加线
const parseline = (k, ele) => {
let style = {}
if (ele.attributes)
for (const key in ele.attributes) {
if (Object.prototype.hasOwnProperty.call(ele.attributes, key)) {
const element = ele.attributes[key]
style[key] = element
}
}
if (style['x1'] && style['y1'] && style['x2'] && style['y2'])
k.comps.push(
CreateDefalutShape(
{
type: 'shape',
points: [
X(style['x1']),
Y(style['y1']),
X(style['x2']),
Y(style['y2'])
],
opacity: Number(style['opacity'] === undefined ? 1 : style['opacity']),
borderColor:
hexToRgba(
style['stroke'],
Number(style['stroke-opacity'] === undefined ? 1 : style['stroke-opacity'])
) || undefined, borderWidth:
style['stroke-width'] === undefined ? 1 : style['stroke-width']
},
undefined
)
)
} // 转换形状
const parepath = (k, ele) => {
let style = {} if (ele.attributes)
for (const key in ele.attributes) {
if (Object.prototype.hasOwnProperty.call(ele.attributes, key)) {
const element = ele.attributes[key]
style[key] = element
}
} if (!style['d']) return
let S = style['d']
S = S.replace(/,/gm, ' ')
for (var r = 0; r < 2; r++)
S = S.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, '$1 $2')
; (S = S.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, '$1 $2')),
(S = S.replace(/([0-9])([+\-])/gm, '$1 $2'))
for (var r = 0; r < 2; r++) S = S.replace(/(\.[0-9]*)(\.)/gm, '$1 $2')
; (S = S.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, '$1 $3 $4 ')),
(S = compressSpaces(S)),
(S = trim(S)) let points: any = []
let segments: any = [] // 获取数据 const GetPathData = () => {
let lastkey = '' //本次key
let M_lastkey = '' // 上一次key let lastpoint = { x: 0, y: 0 }
let controlpoint = { x: 0, y: 0 }
let lastindex = 0 let A1 = 0,
A2 = 0,
A3 = 0,
A4 = 0,
A5 = 0,
A6 = 0,
A7 = 0,
c1 = 0,
c2 = 0
const Path = (key, points) => {
if (
[
'm',
'l',
'h',
'v',
'c',
's',
'q',
't',
'a',
'z',
'M',
'L',
'H',
'V',
'C',
'S',
'Q',
'T',
'A',
'Z'
].indexOf(key) > -1
) {
switch (key) {
case 'Z':
case 'z':
segments.push(5)
break
}
lastindex = 0
M_lastkey = lastkey
lastkey = key return
}
const keylst = ['c', 's', 't', 'q']
if (lastkey && key != undefined)
switch (lastkey) {
case 'M':
lastindex % 2 === 0 && lastindex === 0 &&
(segments.push(1),
(lastpoint.x = Number(key)),
points.push(X(lastpoint.x))) lastindex % 2 === 0 && lastindex > 1 &&
(segments.push(2),
(lastpoint.x = Number(key)),
points.push(X(lastpoint.x))) lastindex % 2 !== 0 &&
((lastpoint.y = Number(key)), points.push(Y(lastpoint.y)))
break case 'm':
lastindex % 2 === 0 && lastindex === 0 &&
(segments.push(1),
(lastpoint.x += Number(key)),
points.push(X(lastpoint.x)))
lastindex % 2 === 0 && lastindex > 1 &&
(segments.push(2),
(lastpoint.x += Number(key)),
points.push(X(lastpoint.x))) lastindex % 2 !== 0 &&
((lastpoint.y += Number(key)), points.push(Y(lastpoint.y))) break
case 'L':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.x = Number(key)),
points.push(X(lastpoint.x)))
lastindex % 2 !== 0 &&
((lastpoint.y = Number(key)), points.push(Y(lastpoint.y)))
break
case 'l':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.x += Number(key)),
points.push(X(lastpoint.x)))
lastindex % 2 !== 0 &&
((lastpoint.y += Number(key)), points.push(Y(lastpoint.y))) break
case 'H':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.x = Number(key)),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y)))
break
case 'h':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.x += Number(key)),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y))) break
case 'V':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.y = Number(key)),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y)))
break
case 'v':
lastindex % 2 === 0 &&
(segments.push(2),
(lastpoint.y += Number(key)),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y)))
break
case 'C':
lastindex % 2 === 0 && points.push(X(key))
lastindex % 2 !== 0 && points.push(Y(key))
if (lastindex % 6 === 4) lastpoint.x = Number(key)
if (lastindex % 6 === 5) lastpoint.y = Number(key)
if (lastindex % 6 === 0) segments.push(4) if (lastindex % 6 === 2) controlpoint.x = Number(key)
if (lastindex % 6 === 3) controlpoint.y = Number(key) break
case 'c':
lastindex % 2 === 0 && points.push(X(lastpoint.x + Number(key)))
lastindex % 2 !== 0 && points.push(Y(lastpoint.y + Number(key))) if (lastindex % 6 === 2)
controlpoint.x = lastpoint.x + Number(key)
if (lastindex % 6 === 3)
controlpoint.y = lastpoint.y + Number(key)
if (lastindex % 6 === 4) lastpoint.x += Number(key)
if (lastindex % 6 === 5) lastpoint.y += Number(key)
if (lastindex % 6 === 0) segments.push(4) if (lastindex % 6 === 2) controlpoint.x = lastpoint.x + Number(key)
if (lastindex % 6 === 3) controlpoint.y = lastpoint.y + Number(key) break
case 'S': lastindex % 4 === 0 &&
(points.push(
X(
keylst.indexOf(M_lastkey.toLowerCase()) < 0
? lastpoint.x
: 2 * lastpoint.x - controlpoint.x
)
),
points.push(
Y(
keylst.indexOf(M_lastkey.toLowerCase()) < 0
? lastpoint.y
: 2 * lastpoint.y - controlpoint.y
)
)) lastindex % 2 === 0 && points.push(X(key))
lastindex % 2 !== 0 && points.push(Y(key)) if (lastindex % 4 === 0) controlpoint.x = Number(key)
if (lastindex % 4 === 1) controlpoint.y = Number(key)
if (lastindex % 4 === 2) lastpoint.x = Number(key)
if (lastindex % 4 === 3) lastpoint.y = Number(key)
if (lastindex % 4 === 0) segments.push(4)
break
case 's': lastindex % 4 === 0 &&
(points.push(
X(
keylst.indexOf(M_lastkey.toLowerCase()) < 0
? lastpoint.x
: 2 * lastpoint.x - controlpoint.x
)
),
points.push(
Y(
keylst.indexOf(M_lastkey.toLowerCase()) < 0
? lastpoint.y
: 2 * lastpoint.y - controlpoint.y
)
))
lastindex % 2 === 0 && points.push(X(lastpoint.x + Number(key)))
lastindex % 2 !== 0 && points.push(Y(lastpoint.y + Number(key)))
if (lastindex % 4 === 0)
controlpoint.x = lastpoint.x + Number(key)
if (lastindex % 4 === 1)
controlpoint.y = lastpoint.y + Number(key)
if (lastindex % 4 === 2) lastpoint.x += Number(key)
if (lastindex % 4 === 3) lastpoint.y += Number(key)
if (lastindex % 4 === 0) segments.push(4)
break case 'Q':
case 'T':
lastindex % 2 === 0 && points.push(X(key))
lastindex % 2 !== 0 && points.push(Y(key))
if (lastindex % 4 === 2) lastpoint.x = Number(key)
if (lastindex % 4 === 3) lastpoint.y = Number(key)
if (lastindex % 4 === 0) segments.push(3)
break
case 'q':
case 't':
lastindex % 2 === 0 && points.push(X(lastpoint.x + Number(key)))
lastindex % 2 !== 0 && points.push(Y(lastpoint.y + Number(key)))
if (lastindex % 4 === 0)
controlpoint.x = lastpoint.x + Number(key)
if (lastindex % 4 === 1)
controlpoint.y = lastpoint.y + Number(key)
if (lastindex % 4 === 2) lastpoint.x += Number(key)
if (lastindex % 4 === 3) lastpoint.y += Number(key)
if (lastindex % 4 === 0) segments.push(3)
case 'A':
if (lastindex % 7 === 0)
(A1 = Number(key)), (c1 = lastpoint.x), (c2 = lastpoint.y)
if (lastindex % 7 === 1) A2 = Number(key)
if (lastindex % 7 === 2) A3 = Number(key) * (Math.PI / 180)
if (lastindex % 7 === 3) A4 = Number(key)
if (lastindex % 7 === 4) A5 = Number(key) if (lastindex % 7 === 5)
(lastpoint.x = Number(key)), (A6 = lastpoint.x)
if (lastindex % 7 === 6)
(lastpoint.y = Number(key)), (A7 = lastpoint.y)
if (lastindex % 7 === 6) {
const x =
(Math.cos(A3) * (c1 - A6)) / 2 +
(Math.sin(A3) * (c2 - A7)) / 2
const y =
(-Math.sin(A3) * (c1 - A6)) / 2 +
(Math.cos(A3) * (c2 - A7)) / 2
const M =
Math.pow(x, 2) / Math.pow(A1, 2) +
Math.pow(y, 2) / Math.pow(A2, 2)
M < 1e-6 &&
(segments.push(2),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y))) if (!(M < 1e-6)) {
const curves = arcToBezier({
px: c1,
py: c2,
cx: A6,
cy: A7,
rx: A1,
ry: A2,
xAxisRotation: A3,
largeArcFlag: A4,
sweepFlag: A5
})
curves &&
curves.forEach(c => {
c &&
(segments.push(4),
points.push(X(c['x1'])),
points.push(Y(c['y1'])),
points.push(X(c['x2'])),
points.push(Y(c['y2'])),
points.push(X(c['x'])),
points.push(Y(c['y'])))
})
}
} break
case 'a':
if (lastindex % 7 === 0)
(A1 = Number(key)), (c1 = lastpoint.x), (c2 = lastpoint.y)
if (lastindex % 7 === 1) A2 = Number(key)
if (lastindex % 7 === 2) A3 = Number(key) * (Math.PI / 180)
if (lastindex % 7 === 3) A4 = Number(key)
if (lastindex % 7 === 4) A5 = Number(key) if (lastindex % 7 === 5)
(lastpoint.x += Number(key)), (A6 = lastpoint.x)
if (lastindex % 7 === 6)
(lastpoint.y += Number(key)), (A7 = lastpoint.y)
if (lastindex % 7 === 6) {
const x =
(Math.cos(A3) * (c1 - A6)) / 2 +
(Math.sin(A3) * (c2 - A7)) / 2
const y =
(-Math.sin(A3) * (c1 - A6)) / 2 +
(Math.cos(A3) * (c2 - A7)) / 2
const M =
Math.pow(x, 2) / Math.pow(A1, 2) +
Math.pow(y, 2) / Math.pow(A2, 2)
M < 1e-6 &&
(segments.push(2),
points.push(X(lastpoint.x)),
points.push(Y(lastpoint.y))) if (!(M < 1e-6)) {
const curves = arcToBezier({
px: c1,
py: c2,
cx: A6,
cy: A7,
rx: A1,
ry: A2,
xAxisRotation: A3,
largeArcFlag: A4,
sweepFlag: A5
})
curves &&
curves.forEach(c => {
c &&
(segments.push(4),
points.push(X(c['x1'])),
points.push(Y(c['y1'])),
points.push(X(c['x2'])),
points.push(Y(c['y2'])),
points.push(X(c['x'])),
points.push(Y(c['y'])))
})
}
} break default:
break
} lastindex++
} const tonkes = S.split(' ') tonkes.forEach((element, _index) => {
Path(element, points)
})
} GetPathData()
let text: any = CreateDefalutShape(
{
type: 'shape',
points: points,
segments: segments
},
undefined
) if ('fill' in style) {
text.background = hexToRgba(
style['fill'],
Number(style['fill-opacity'] === undefined ? 1 : style['fill-opacity'])
)
} else {
text.background = hexToRgba('#000', Number(style['fill-opacity'] === undefined ? 1 : style['fill-opacity']))
} if ('stroke-linejoin' in style) text.borderJoin = style['stroke-linejoin']
if ('stroke-linecap' in style) text.orderCap = style['stroke-linecap']
if ('stroke' in style)
text.borderColor =
hexToRgba(style['stroke'], Number(style['stroke-opacity'] === undefined ? 1 : style['stroke-opacity'])) ||
undefined
if ('opacity' in style) text.opacity = Number(style['opacity'] === undefined ? 1 : style['opacity'])
text.borderWidth =
style['stroke-width'] === undefined ? 1 : style['stroke-width'] if (ele?.attributes?.class) { function configobj(arr) {
const result = {}
if (arr && arr.length > 0) {
let currentKey = ""
let currentValue = ""
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
currentKey = arr[i].match(/([^:;]\S[^:;]+)(?=\:)/)[0]
currentValue = arr[i].match(/(?<=\:)([^:;]\S[^:;]+)/)[0]
}
result[currentKey] = currentValue
}
}
return result
}
var sls = StyleClasse.match(/(\w*?-\w*)\s+\{\s+(\w*)\:\s+.?\w*.?\s+\}/g) || StyleClasse.match(/(?<=\.).*?\}/g)
sls && sls.forEach(element => { var r = RegExp(".*" + ele.attributes.class + ".*", "i"); if (r.test(element)) { var val = element.substring(element.indexOf('{') + 1, element.length).replace(/}/g, '').replace(/\s/g, "").match(/([^;]\S[^;]+)\:([^;]\S[^;]+)/g)
var values = configobj(val)
if (values) {
if ('fill' in values) {
text.background = hexToRgba(
values['fill'],
Number(values['fill-opacity'] === undefined ? 1 : values['fill-opacity'])
)
} if ('stroke-linejoin' in values) text.borderJoin = values['stroke-linejoin']
if ('stroke-linecap' in values) text.orderCap = values['stroke-linecap']
if ('stroke' in values)
text.borderColor =
hexToRgba(values['stroke'], Number(values['stroke-opacity'] === undefined ? 1 : values['stroke-opacity'])) ||
undefined
if ('opacity' in values) text.opacity = Number(values['opacity'] === undefined ? 1 : values['opacity'])
text.borderWidth =
values['stroke-width'] === undefined ? 1 : values['stroke-width'] } } }); } k.comps.push(text)
} let linearGradient_list: any = []
let linearGradient_comp: any
// 渐变色
const linearGradient = ele => {
if (ele && ele.attributes && ele.attributes.id) {
linearGradient_comp = new Object()
linearGradient_comp.id = ele.attributes.id
ele.attributes.x1 && (linearGradient_comp.x1 = X(ele.attributes.x1))
ele.attributes.y1 && (linearGradient_comp.y1 = Y(ele.attributes.y1))
ele.attributes.x2 && (linearGradient_comp.x2 = X(ele.attributes.x2))
ele.attributes.y2 && (linearGradient_comp.y2 = Y(ele.attributes.y2))
linearGradient_comp.styles = []
linearGradient_list.push(linearGradient_comp)
}
ele.children &&
ele.children.forEach(element => {
element.attributes &&
linearGradient_comp.styles.push({
offset: element.attributes.offset,
color: element.attributes.style
})
}) } //样式
const parseClass = (val, defs: any = undefined) => { if (val && val.value) {
StyleClasse += val.value
}
val && val.children && val.children.forEach(o => parseClass(o)) if (defs) {
// 样式对象
}
} const parseSvg = (k, list, _value = undefined) => {
list &&
list.forEach((ele, _index) => { if (ele.type === 'element' && ele.name === 'style') {
// 样式
parseClass(ele)
}
if (ele.type === 'element' && ele.name === 'linearGradient') {
// 渐变色
linearGradient(ele)
} if (ele.type === 'element' && ele.name === 'text') {
parseText(k, ele) return
}
if (ele.children && ele.children.length > 0) {
parseSvg(k, ele.children, ele.value)
} else if (ele.attributes) { switch (ele.name || ele.type) {
case 'g':
parseSvg(k, ele.children, ele.value)
break
case 'circle':
k.comps.push(
CreateDefalutShape(
{
type: 'circle',
rect: [
X(ele.attributes.cx) - X(ele.attributes.r),
Y(ele.attributes.cy) - Y(ele.attributes.r),
X(ele.attributes.r) * 2,
Y(ele.attributes.r) * 2
]
},
ele.attributes
)
)
break
case 'rect': ele.attributes.d = Rect2path(X(ele.attributes.x), Y(ele.attributes.y), X(ele.attributes.width), Y(ele.attributes.height), X(ele.attributes.rx), Y(ele.attributes.ry))
parepath(k, ele) break
case 'ellipse': // ele.attributes.d = Ellipse2path(X(ele.attributes.cx), Y(ele.attributes.cy), X(ele.attributes.rx), Y(ele.attributes.ry)) // parepath(k, ele) k.comps.push(
CreateDefalutShape(
{
type: 'oval',
rect: [
X(ele.attributes.cx) - X(ele.attributes.rx),
Y(ele.attributes.cy) - Y(ele.attributes.ry),
X(ele.attributes.rx) * 2,
Y(ele.attributes.ry) * 2
]
},
ele.attributes
)
) break
case 'path':
parepath(k, ele)
break case 'polygon':
parsepolygon(k, ele) break
case 'line':
parseline(k, ele) break case 'image':
parseImage(k, ele) break
default:
break
}
} })
}
StyleClasse = ''
URL &&
ht.Default.xhrLoad(URL, text => {
parse(text)
.then(json => { const ToNumberArray = function (x) {
for (
var S = trim(compressSpaces((x || '').replace(/,/g, ' '))).split(
' '
),
r = 0;
r < S.length;
r++
)
S[r] = parseFloat(S[r])
return S
} json.attributes &&
((k.width = Number(json.attributes.width === undefined ? 512 : json.attributes.width)),
(k.height = Number(json.attributes.height === undefined ? 512 : json.attributes.height)))
if (json.attributes.viewBox) {
const viewBox = ToNumberArray(json.attributes.viewBox)
scaleX = (viewBox[2] - viewBox[0]) / k.width
scaleY = (viewBox[3] - viewBox[1]) / k.height
}
refX = parseFloat(json.attributes.refX) || 0
refY = parseFloat(json.attributes.refY) || 0 json.children && parseClass(undefined, json.children.map(o => o.name === 'defs')) json.children && parseSvg(k, json.children) JsonToView(k, oBJht)
})
.catch(error => {
ElMessage({
type: 'error',
message: error?.toString()
})
})
})
file &&
parse(file)
.then(json => {
const ToNumberArray = function (x) {
for (
var S = trim(compressSpaces((x || '').replace(/,/g, ' '))).split(
' '
),
r = 0;
r < S.length;
r++
)
S[r] = parseFloat(S[r])
return S
} json.attributes &&
json.attributes.width &&
(k.width = Number(
json.attributes.width.toLowerCase().replace('px', '')
)) json.attributes &&
json.attributes.height &&
(k.height = Number(
json.attributes.height.toLowerCase().replace('px', '')
))
if (json.attributes.viewBox) {
const viewBox = ToNumberArray(json.attributes.viewBox)
scaleX = (viewBox[2] - viewBox[0]) / k.width
scaleY = (viewBox[3] - viewBox[1]) / k.height
}
refX = parseFloat(json.attributes.refX) || 0
refY = parseFloat(json.attributes.refY) || 0 json.children && parseClass(undefined, json.children.filter(o => o.name === 'defs'))
json.children && parseSvg(k, json.children) JsonToView(k, oBJht)
callback && callback()
})
.catch(error => {
ElMessage({
type: 'error',
message: error?.toString()
})
})
} export default SvgToShape
二维Svg转矢量 不支持Svg2.0的更多相关文章
- 微信公众平台中临时二维码的scene_id为32位非0整型
原文:微信公众平台中临时二维码的scene_id为32位非0整型 微信公众平台中临时二维码的scene_id为32位非0整 ...
- 好推二维码如何通过应用宝微下载支持微信自动打开APP下载?
好推二维码 官网 http://www.hotapp.cn 1. 为什么使用应用宝微下载? APP下载二维码,通过微信扫描下载的时候,微信目前只支持应用宝微下载,才能在微信里直接打开下载,否则就需要在 ...
- 动态生成二维码插件 jquery.qrcode.js
前段时间做项目,需要动态生成一个二维码,于是就在网上找了一下发现一个jquery插件jquery.qrcode.js,所以今天就简单说一下这个插件的使用: jquery.qrcode.js是依赖jqu ...
- Jquery.Qrcode在客户端动态生成二维码并添加自定义Logo
0 Jquery.Qrcode简介 Jquery.Qrcode.js是一个在浏览器端基于Jquery动态生成二维码的插件,支持Canvas和Table两种渲染方式,它的优点是在客户端动态生成,减轻了服 ...
- Java 验证码、二维码
Java 验证码.二维码 资源 需要: jelly-core-1.7.0.GA.jar网站: http://lychie.github.io/products.html将下载下来的 jelly ...
- 微信公共服务平台开发(.Net 的实现)9-------处理二维码
今天我们来共同学习一下微信公共服务平台中一个重要内容---二维码扫描.众所周知二维码目前应用范围很广,在这里不再叙述背景了,但是值得一提的是目前大家手机上面应用的二维码扫描工具是支持的都是QR码和PD ...
- java利用Google Zxing实现 二维码生成与解析
1.引入zxing 2.使用下面两个类:QRCodeUtil.java和BufferedImageLuminanceSource.java 3.新建单元测试类 复制下面测试代码即可. 1.pom文件中 ...
- iOS,object-c传参c语言的二维数组
有那么一瞬间,懒得用NSArray,NSNumber,NSValue等一大堆蛋疼的转换,所以就定义了一个C的二维数组,反正OC支持C混编,可是蛋疼往往是传递的,这里不疼了,哪里就要疼,想把一个c的二维 ...
- Swift:使用系统AVFoundation实现二维码扫描和生成
系统提供的AVCaptureSession仅仅适用于iOS7.0以上的系统.之前的请用Zbar来替代 下载地址:http://download.csdn.net/detail/huobanbengku ...
- Java生成微信二维码及logo二维码
依赖jar包 二维码的实现有多种方法,比如 Google 的 zxing 和日本公司的 QrCode,本文以 QrCode 为例. QrCode.jar:https://pan.baidu.com/s ...
随机推荐
- python+POM项目设计模式
分为三层: 第一层:common对selenium进行二次封装,定位元素,操作元素的一些方法,公共方法比如连接数据库.读写yml文件等 第二层:页面封装pages 第三层:测试用例cases
- pip3 install
python3 -m venv tutorial-env source tutorial-env/bin/activatepip3 install *deactivate
- DOS下的一些命令
DOS一些命令 1.查看无线密码 netsh wlan show profiles #显示所有本地电脑加入过的wlan netsh wlan show profiles name=&q ...
- java和js 用正则表达式切割省市县的代码
String s= "安徽省合肥市肥西县上派镇"; // String regex="(\\?[^省]+自治区|.*?省|.*?行政区|.*?市)(\\?[^市]+自治州 ...
- bilibili经典面试题
1. 如何向面试官解释什么是Redis,看看普通人和高手是如何回答的?_哔哩哔哩_bilibili 2.Java面试热点问题,synchronized原理剖析与优化_哔哩哔哩_bilibili 3.黑 ...
- JSP课设:学生选课系统(附源码+调试)
JSP学生选课管理系统学生选课管理系统功能概述(1)登录模块分为两种角色:学生角色.教师角色 (2)教师模块:选课管理功能为对课程信息(课程编号.名称.学分)进行添加.修改.删除操作:学生信息功能对学 ...
- 利用 fastjson 的 toJSONStringWithDateFormat 方法,将Date 格式化 为常见类型的时间
利用 fastjson 的 toJSONStringWithDateFormat 方法,将Date 格式化 为常见类型的时间 JSON.toJSONStringWithDateFormat(nrcSt ...
- 把VScode插件提示abc的提示给移到最后
把VScode插件提示abc的提示给移到最后 解决方法 打开设置,在搜索中输入editor.snippetSuggestions,然后将选项改为top,就可以解决了 top:就是将你插件提示放到最上面 ...
- python下载文件headers
from aiohttp import webfrom urllib.parse import quote r = web.Response()# r.content_type = 'applicat ...
- 简单的python线程池实现线程安全demo
from concurrent.futures import ThreadPoolExecutor import threading import time import sys sys.path.a ...