js实现环形菜单效果

点击中间的圆点,会弹出环形菜单,效果图:

 

代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>javascript ring menu</title>
    <style media="screen">
        html,body {
            height: 99%;
            width: 99%;
        }
        .plus {
            position: relative;
            margin: 100px;
        }

        .plus::after,
        .plus::before {
            position: absolute;
            content: '';
            display: inline-block;
            border: 1px solid silver;
            opacity: 0.8;
        }

        .plus::before {
            width: 11px;
            height: 1px;
            left: 11px;
            top: 16px;
        }

        .plus::after {
            width: 1px;
            height: 11px;
            left: 16px;
            top: 11px;
        }

        .ring {
            width: 10px;
            height: 10px;
            position: relative;
            display: inline-block;
            padding: 1em;
            font-size: 12px;
            border-radius: 50% 50%;
            box-shadow: 1px 1px 5px 0 rgba(89, 167, 255, 0.5);
        }

        .ring:hover {
            box-shadow: 1px 1px 5px 0 rgba(89, 167, 255, 0.8);
        }

        .circle {
            position: absolute;
            cursor: pointer;
            padding: 0.8em 0.5em;
            display: inline-block;
            border-radius: 50% 50%;
            border: 1px solid rgba(89, 167, 255, 0.2);
            box-shadow: 1px 3px 40px 0 rgba(89, 167, 255, 0.3);
            overflow: hidden;
            word-break: keep-all;
            transition: left 0.5s linear, top 0.5s linear, color 0.5s linear, background-color 0.5s linear, box-shadow 0.5s linear;
        }

        .circle:hover {
            color: #fff;
            background-color: rgba(89, 167, 255, 0.8);
            box-shadow: 1px 3px 40px 0 rgba(89, 167, 255, 1);
            z-index: 100;
        }

        .ring.selected>.circle {
            display: inline-block;
            opacity: 1;
            z-index: 10;
        }

        .node-hide {
            width: 0px;
            height: 0px;
            opacity: 0;
            left: calc(30%) !important;
            top: calc(30%) !important;
        }
    </style>
</head>

<body>
    <div class="ring plus">
        <div class="circle">
            属性
        </div>
        <div class="circle">
            事件
        </div>
        <div class="circle">
            类型
        </div>
        <div class="circle">
            关联
        </div>
        <div class="circle">
            更多
        </div>
    </div>
</body>
<script type="text/javascript">
    var data = [{
            title: '属性'
        },
        {
            title: '事件'
        },
        {
            title: '类型'
        },
        {
            title: '关联'
        }
    ];

    /**
     * R 可以考虑通过传参动态设置
     **/
    function initRing(ctn, data) {
        initByData(data);

        var items = ctn.querySelectorAll('.circle'),
            R = 50, // 圆半径
            angle = 360 / (items.length),
            offsetX = getStyle(ctn).width / 2, // 中心点x轴偏移值
            offsetY = getStyle(ctn).height / 2; // 中心点y轴偏移值
        Array.from(items).map(function(item, index) {
            var dw = getStyle(item).width / 2,
                dh = getStyle(item).height / 2; // 计算菜单坐标
            var hudu = (2 * Math.PI / 360) * angle * index,
                left = (Math.cos(hudu) * R + offsetX - dw).toFixed(2),
                top = (Math.sin(hudu) * R + offsetY - dh).toFixed(2);

            item.style.setProperty('left', left + 'px');
            item.style.top = top + 'px';
            item.classList.add('node-hide');
        });

        ctn.addEventListener('click', function() {
            var cls = Array.from(this.classList),
                ctnr = this,
                items = Array.from(ctnr.querySelectorAll('.circle'));
            if (cls.includes('selected')) {
                this.classList.remove('selected');
                items.map(function(item) {
                    item.classList.add('node-hide');
                });
            } else {
                this.classList.add('selected');
                items.map(function(item) {
                    item.classList.remove('node-hide');
                });
            }
            event.stopPropagation();
        });

        function initByData(data) {
            if (data) {
                data.map(function(item) {
                    var divDom = document.createElement('div');
                    divDom.classList.add('circle');
                    divDom.innerText = item.title;
                    ctn.appendChild(divDom);
                });
            }
        }

        function getStyle(domObj) {
            var style = document.defaultView.getComputedStyle(domObj);
            var width = style.width.replace('px', '') * 1 + style['padding-left'].replace('px', '') * 1 + style['padding-right'].replace('px', '') * 1,
                height = style.height.replace('px', '') * 1 + style['padding-top'].replace('px', '') * 1 + style['padding-bottom'].replace('px', '') * 1;
            return {
                width: width,
                height: height
            };
        }
    }
    
    initRing(document.querySelector('.ring'), data)
</script>

</html>

 

posted @ 2018-04-25 15:18  【云】风过无痕  阅读(3584)  评论(2编辑  收藏  举报