首页 > 其他分享 >二维Svg转矢量 不支持Svg2.0

二维Svg转矢量 不支持Svg2.0

时间:2023-01-16 10:33:10浏览次数:27  
标签:style const && Svg2.0 Svg ele 二维 key attributes

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

 

标签:style,const,&&,Svg2.0,Svg,ele,二维,key,attributes
From: https://www.cnblogs.com/xjserver/p/17050433.html

相关文章

  • 找出二维数组中某元素的所有对角元素
    -----------------------------------------------------------------------------------------------------------写这篇文章的目的,是为了很好的理解八皇后问题,网上一大堆......
  • 区间DP-二维前缀和-差分-6292. 子矩阵元素加 1
    304.二维区域和检索-矩阵不可变DescriptionDifficulty:中等RelatedTopics:设计,数组,矩阵,前缀和给定一个二维矩阵matrix,以下类型的多个请求:计算其子矩形......
  • 25 二维直方图
    25二维直方图opencv知识点:计算直方图数据-calcHist四舍五入浮点数-cvRound寻找最小/最大值-minMaxLoc本课所解决的问题:如何绘制HSV图像的二维直方图?1.二......
  • php 将二维数组处理成以某一列为key,某一列为value的一维数组
    $list=[0=>['id'=>1001,'name'=>'张三'],1=>['id'=>2091,'name'=>'李四']];array_combine(arr......
  • 抽奖动画 - 播放svga动画
    svga动画本文介绍的动画不是css,js动画,是使用插件播放svga文件。1.需求UI同学在做一个春节活动,活动中需要有个开场动画,原本想的简单,不涉及接口调用逻辑,就直接用做一个gif......
  • react中二维码生成
    参考文档:https://blog.csdn.net/weixin_45022563/article/details/124843593 awesomeqr/react案例:注意需要给父级div设置高宽下载:yarnadd@awesomeqr/react......
  • 二维码QRCode
    一、二维码介绍 二维码的应用越来越多,开发中会经常使用,这里主要从二维码的介绍、客户端生成与服务器端生成三个方面讲解二维码。二维码又称二维条码,常见的二维码为QRCode,Q......
  • customElement包装svg的iconfont
    阿里巴巴的iconfont很好用,但是1.小项目不友好,即便你只需要一个图标,也需要建一个项目,非常冗余。2.图标修改不友好,每次都要生成新的文件或者链接。3.对一些无法访问外网的......
  • C++ 使用 new 创建二维数组
    C++使用new创建二维数组最直接的方法就是 ​​newT[M][N]​​​。返回的指针类型是 ​​T(*)[N]​​​,它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内......
  • 74. 搜索二维矩阵
    问题链接https://leetcode.cn/problems/search-a-2d-matrix/description/解题思路我们可以确定,数据是有序的。所以我们有2种办法用二分来解决。第一种,我们可以写个下标......