svg3

全部改写成动态数据渲染

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }

    body {
        height: 100vh;
    }
    </style>
    <script type="text/javascript">
    window.onload = () => {
        let svgNS = 'http://www.w3.org/2000/svg'
        let body = document.getElementsByTagName('body')[0]

        // 中心坐标
        let centerX = 600
        let centerY = 480

        let data = {
            centerNode: { text: '大厂' },
            otherNode: [
                { x: 400, y: 400, text: '字节' },
                { x: 200, y: 500, text: '阿里' },
                { x: 800, y: 700, text: '腾讯' },
                { x: 350, y: 700, text: '百度' },
                { x: 650, y: 300, text: '快手' },
                { x: 950, y: 450, text: '滴滴' }
            ]
        }


        let fragment = document.createDocumentFragment()
        let oSvg = createTag('svg', { 'xmlns': svgNS, 'width': '100%', 'height': '100%' })

        function addLine(item) {
            let g1 = createTag('g', { 'style': 'cursor:pointer;' })
            let line1 = createTag('line', { 'x1': item.x, 'y1': item.y, 'x2': centerX, 'y2': centerY, 'stroke': 'black', 'stroke-width': '1' })
            let line11 = createTag('line', { 'x1': item.x, 'y1': item.y, 'x2': centerX, 'y2': centerY, 'stroke': 'transparent', 'stroke-width': '6' })
            let rect1 = createTag('rect', { 'width': '20', 'height': '20', 'x': (centerX + item.x) / 2 - 10, 'y': (centerY + item.y) / 2 - 10, 'rx': '5', 'fill': '#ccc', 'stroke': 'black', 'stroke-width': '1' })
            let text1 = createTag('text', { 'x': (centerX + item.x) / 2, 'y': (centerY + item.y) / 2 + 6, 'font-size': '16', 'text-anchor': 'middle' })
            text1.innerHTML = '?'
            g1.appendChild(line1)
            g1.appendChild(line11)
            g1.appendChild(rect1)
            g1.appendChild(text1)
            oSvg.appendChild(g1)
        }

        function addOtherTag(item) {
            let g2 = createTag('g', { 'style': 'cursor:pointer;' })
            let circle2 = createTag('circle', { 'r': '30', 'cx': item.x, 'cy': item.y, 'fill': 'white', 'stroke': 'blue', 'stroke-width': '2' })
            let text2 = createTag('text', { 'x': item.x, 'y': item.y + 8, 'font-size': '16', 'text-anchor': 'middle' })
            text2.innerHTML = item.text
            g2.appendChild(circle2)
            g2.appendChild(text2)
            oSvg.appendChild(g2)
        }

        function addTag() {
            let g3 = createTag('g', { 'style': 'cursor:pointer;' })
            let circle3 = createTag('circle', { 'r': '50', 'cx': centerX, 'cy': centerY, 'fill': 'white', 'stroke': 'red', 'stroke-width': '2' })
            let text3 = createTag('text', { 'x': centerX, 'y': centerY + 8, 'font-size': '16', 'text-anchor': 'middle' })
            text3.innerHTML = data.centerNode.text
            g3.appendChild(circle3)
            g3.appendChild(text3)
            oSvg.appendChild(g3)
        }

        // 其他⚪和连线  
        data.otherNode.forEach((item, index) => {
            addLine(item)
            addOtherTag(item)
        })
        
        // 添加中心⚪
        addTag()
        fragment.appendChild(oSvg)
        body.appendChild(fragment)
    }

    function createTag(svgElm, attrObj) {
        let domObj = document.createElementNS('http://www.w3.org/2000/svg', svgElm)
        for (let item in attrObj) {
            domObj.setAttribute(item, attrObj[item])
        }
        return domObj
    }
    </script>
</head>

<body>
</body>

</html>

均匀分布各个○形

注意Math.sin里面传的需是弧度

// 中心坐标
        let centerX = 600
        let centerY = 480

        let data = {
            centerNode: { text: '大厂' },
            otherNode: [
                { text: '字节' },
                { text: '阿里' },
                { text: '腾讯' },
                { text: '百度' },
                { text: '快手' },
                { text: '滴滴' }
            ]
        }

        let circleNum = data.otherNode.length // 圆形数量
        console.log('圆形数量',circleNum)
        let angleNum = 360/circleNum   // 每个圆形占的角度
        console.log('圆形角度',angleNum)
        let othR = 160

        for(let i=0; i<circleNum; i++) {
            console.log(i)
            let y = Math.sin(i*angleNum*Math.PI/180)*othR + centerY
            let x = Math.cos(i*angleNum*Math.PI/180)*othR + centerX
            console.log(x,y)
            data.otherNode[i].x = x
            data.otherNode[i].y = y
        }
// 弹性公式
function startMove(elm,sr,er) {
        let nowR = sr 
        let overR = er
        elm.speed = 0     
        clearInterval(elm.timer)
        elm.timer = setInterval(()=>{
            elm.speed+= (overR-nowR)/7  // 弹性系数 速度更新1
            elm.speed*= 0.75   // 摩擦系数  速度更新2
            // console.log(elm.speed)
            if(Math.abs(overR-nowR)<=1 && Math.abs(elm.speed)<=1){
                clearInterval(elm.timer)
                elm.setAttribute('r',overR)
            }else{
                nowR+=elm.speed
                console.log(nowR)
                elm.setAttribute('r',nowR)
            }
        },30)
    }

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }

    body {
        height: 100vh;
    }
    </style>
    <script type="text/javascript">
    window.onload = () => {
        let svgNS = 'http://www.w3.org/2000/svg'
        let body = document.getElementsByTagName('body')[0]

        // 中心坐标
        let centerX = 600
        let centerY = 480

        let data = {
            centerNode: { text: '大厂' },
            otherNode: [
                { text: '字节' },
                { text: '阿里' },
                { text: '腾讯' },
                { text: '百度' },
                { text: '快手' },
                { text: '滴滴' }
            ]
        }

        let circleNum = data.otherNode.length // 圆形数量
        console.log('圆形数量', circleNum)
        let angleNum = 360 / circleNum // 每个圆形占的角度
        console.log('圆形角度', angleNum)
        let othR = 160

        for (let i = 0; i < circleNum; i++) {
            console.log(i)
            let y = Math.sin(i * angleNum * Math.PI / 180) * othR + centerY
            let x = Math.cos(i * angleNum * Math.PI / 180) * othR + centerX
            console.log(x, y)
            data.otherNode[i].x = x
            data.otherNode[i].y = y
        }



        let fragment = document.createDocumentFragment()
        let oSvg = createTag('svg', { 'xmlns': svgNS, 'width': '100%', 'height': '100%' })

        function addLine(item) {
            let g1 = createTag('g', { 'style': 'cursor:pointer;', 'class': 'lineStyle' })
            let line1 = createTag('line', { 'x1': item.x, 'y1': item.y, 'x2': centerX, 'y2': centerY, 'stroke': 'black', 'stroke-width': '1' })
            let line11 = createTag('line', { 'x1': item.x, 'y1': item.y, 'x2': centerX, 'y2': centerY, 'stroke': 'transparent', 'stroke-width': '6' })
            let rect1 = createTag('rect', { 'width': '20', 'height': '20', 'x': (centerX + item.x) / 2 - 10, 'y': (centerY + item.y) / 2 - 10, 'rx': '5', 'fill': '#ccc', 'stroke': 'black', 'stroke-width': '1' })
            let text1 = createTag('text', { 'x': (centerX + item.x) / 2, 'y': (centerY + item.y) / 2 + 6, 'font-size': '16', 'text-anchor': 'middle' })
            text1.innerHTML = '?'
            g1.appendChild(line1)
            g1.appendChild(line11)
            g1.appendChild(rect1)
            g1.appendChild(text1)
            oSvg.appendChild(g1)
        }

        function addOtherTag(item) {
            let g2 = createTag('g', { 'style': 'cursor:pointer;', 'class': 'circleStyle' })
            let circle2 = createTag('circle', { 'r': 30, 'cx': item.x, 'cy': item.y, 'fill': 'white', 'stroke': 'blue', 'stroke-width': '2' })
            let text2 = createTag('text', { 'x': item.x, 'y': item.y + 8, 'font-size': '16', 'text-anchor': 'middle' })
            text2.innerHTML = item.text
            g2.appendChild(circle2)
            g2.appendChild(text2)
            oSvg.appendChild(g2)
        }

        function addTag() {
            let g3 = createTag('g', { 'style': 'cursor:pointer;'})
            let circle3 = createTag('circle', { 'r': '50', 'cx': centerX, 'cy': centerY, 'fill': 'white', 'stroke': 'red', 'stroke-width': '2' })
            let text3 = createTag('text', { 'x': centerX, 'y': centerY + 8, 'font-size': '16', 'text-anchor': 'middle' })
            text3.innerHTML = data.centerNode.text
            g3.appendChild(circle3)
            g3.appendChild(text3)
            oSvg.appendChild(g3)
        }

        data.otherNode.forEach((item, index) => {
            addLine(item)
            addOtherTag(item)
        })
        // 添加中心⚪
        addTag()

        fragment.appendChild(oSvg)
        body.appendChild(fragment)

        bindTag()

    }

    function createTag(svgElm, attrObj) {
        let domObj = document.createElementNS('http://www.w3.org/2000/svg', svgElm)
        for (let item in attrObj) {
            domObj.setAttribute(item, attrObj[item])
        }
        return domObj
    }

    function bindTag() {
        let aLine = document.querySelectorAll('.lineStyle')
        let aCircle = document.querySelectorAll('.circleStyle')
        for (var i = 0; i < aLine.length; i++) {
            (function(i) {
                aLine[i].onmouseenter = function() {
                    this.getElementsByTagName('line')[0].setAttribute('stroke','blue')
                    this.getElementsByTagName('rect')[0].setAttribute('fill','orange')
                }
                aLine[i].onmouseleave = function() {
                    this.getElementsByTagName('line')[0].setAttribute('stroke','black')
                    this.getElementsByTagName('rect')[0].setAttribute('fill','#ccc')
                }
            })(i)
        }

        for(let i =0 ; i < aCircle.length; i++) {
            aCircle[i].onmouseenter = () => {
                startMove(aCircle[i].getElementsByTagName('circle')[0], 30, 40)
                let preNode = aCircle[i].previousElementSibling
                preNode.getElementsByTagName('line')[0].setAttribute('stroke','blue')
                preNode.getElementsByTagName('rect')[0].setAttribute('fill','orange')
            }
            aCircle[i].onmouseleave = () => {
                startMove(aCircle[i].getElementsByTagName('circle')[0], 40, 30)
                let preNode = aCircle[i].previousElementSibling
                preNode.getElementsByTagName('line')[0].setAttribute('stroke','black')
                preNode.getElementsByTagName('rect')[0].setAttribute('fill','#ccc')
            }
        }

    }

    function startMove(elm,sr,er) {
        let nowR = sr 
        let overR = er
        elm.speed = 0
        clearInterval(elm.timer)
        elm.timer = setInterval(()=>{
            elm.speed+= (overR-nowR)/7
            elm.speed*= 0.75
            // console.log(elm.speed)
            if(Math.abs(overR-nowR)<=1 && Math.abs(elm.speed)<=1){
                clearInterval(elm.timer)
                elm.setAttribute('r',overR)
            }else{
                nowR+=elm.speed
                console.log(nowR)
                elm.setAttribute('r',nowR)
            }
        },30)
    }

    </script>
</head>

<body>
</body>

</html>