JQuery蜂巢图插件

916 阅读3分钟

效果如图:

1.css

.wrap {
    margin:20px auto 0px auto;
}

.sexangle {
    background: none;
    display: inline-block;
    /* position: relative; */
    line-height: 58px;
    text-align: center;
    color: #ffffff;
    font-size: 14px;
    text-decoration: none;
    float: left;
    margin-top: 35px;
    margin-right: 5px;
    box-sizing: border-box;
    background-size: cover;
    display: inline-block;
    opacity: 1;
}
.sexangle:hover{
    opacity: 0.8;
}

.sexangle span:nth-child(1) {
    width: 0;
    height: 0;
    display: block;
    overflow: hidden;
    position: absolute;
    border-left: 50px dotted transparent;
    border-right: 50px dotted transparent;
    border-bottom: 30px solid none;
    left: 0px;
    top: -30px;
}

.sexangle span:nth-child(2) {
    width: 0;
    height: 0;
    display: block;
    overflow: hidden;
    position: absolute;
    border-left: 50px dotted transparent;
    border-right: 50px dotted transparent;
    border-top: 30px solid none;
    bottom: -30px;
    left: 0px;
}
.sexangle-hide{
    z-index: -1;
    background:none;
    pointer-events: none;
    visibility: hidden;

}
.sexangle-hide span{
    z-index: -1;
    background:none;
    pointer-events: none;
    visibility: hidden;
}


.hc-popover{
    background:rgba(51,51,51,1);
    border-radius:3px;
    opacity:0.9;
    padding: 8px;
}
.hc-popover .title{
    width:100%;
    font-size:12px;
    font-family:PingFangSC-Regular;
    color:rgba(255,255,255,1);
    line-height:20px;
    border-bottom:1px solid rgba(0,0,0,0.6);
    text-align: left;
}

.hc-popover .message{
    font-size:12px;
    font-family:PingFangSC-Regular;
    color:rgba(255,255,255,1);
    line-height:20px;
    width:100%;
    text-align: left;
}

.tile-line{
    display: block;
    width:100%;
    height:20px;
    position: relative;
    padding:0px;
    margin:0px;
    line-height: 20px;
    text-align: center;
    box-sizing: border-box;
    user-select: none;
}

2.js


(function ($, window, document, undefined) {
    var _pluginName = 'jqHoneycomb';

    var defaults = {
        Hosts: [],
        MaxWidth: 600,
        MaxLength: 0,
        TileWidth: 100
    };

    function getTilesArr(options) {
        // debugger
        var hosts = options.Hosts || [];
        var sum = hosts.length;
        //边长度
        var lines = getMinLines(sum);
        //横切最大长度
        var maxLen = lines * 2 - 1;

        var _TileWidth = options.MaxWidth
            , _MaxLength
            , _MaxWidth
            , _WrapWidth
            , _BorderTopWidth
            , _TileHeight;

        if (maxLen * (_TileWidth + 4) > _TileWidth) {

            _TileWidth = Math.floor((options.MaxWidth - maxLen * 4) / maxLen);
        }

        var arr = [];
        var tileIndex = 0;
        for (var i = lines; i < maxLen; i++) {

            var tiles = new Array(i);
            for (var n = 0; n < i; n++) {

                tileIndex += 1;
                tiles[n] = {
                    tileIndex: tileIndex
                };
            }

            arr.push({
                tiles: tiles,
                maxLen: maxLen,
                diff: maxLen - i
            });
        }
        for (var i = maxLen; i >= lines; i--) {

            var tiles = new Array(i);
            for (var n = 0; n < i; n++) {

                tileIndex += 1;
                tiles[n] = {
                    tileIndex: tileIndex
                }
            }

            arr.push({
                tiles: tiles,
                maxLen: maxLen,
                diff: maxLen - i
            });
        }

        //获取所有最外层六边形ID
        /*
          lines 4 tileIndex 37
          1                     4
          1+4=5                 4+5
          1+4+5=10              4+5+6
          1+4+5+6=16            4+5+6+7
          1+4+5+6+7=23          4+5+6+7+6
          1+4+5+6+7+6=29        4+5+6+7++6+5
          1+4+5+6+7+6+5 = 34 4+5+6+7+6+5+4 = 37
          34 35 36 37
        */
        var outSides = [];
        for (var i = 1; i <= lines; i++) {
            outSides.push(i);// 1 2 3 4
            outSides.push(tileIndex - i + 1);// 34 35 36 37
        }
        //左半圈ID
        var preStart = 1;
        for (var i = 0; i < lines; i++) {
            var next = preStart + lines + i
            outSides.push(next);
            preStart = next;
        }
        for (var i = maxLen - 1; i > lines; i--) {
            var next = preStart + i
            outSides.push(next);
            preStart = next;
        }
        //右半圈ID
        var preEnd = lines;
        for (var i = lines; i < maxLen; i++) {
            var next = preEnd + i + 1;
            outSides.push(next);
            preEnd = next;
        }
        for (var i = maxLen - 1; i > lines; i--) {
            var next = preEnd + i
            outSides.push(next);
            preEnd = next;
        }

        //去重 & 排序 得到最终最外层六边形ID数组
        outSides = unique(outSides).sort((a, b) => a - b);
        //截取不需要显示的ID
        var unnecessary = tileIndex - sum;//
        outSides = outSides.splice(outSides.length - unnecessary, unnecessary);

        var _l = 0;
        arr = arr.map((t, i) => {
            if (t) {

                t.tiles = (t.tiles || []).map((o, j) => {
                    o.show = !outSides.includes(o.tileIndex);
                    o.data = hosts[(i * _l) + j];

                    return o;
                });
                _l = (t.tiles || []).length;
            }
            return t;
        });


        _MaxLength = maxLen;
        _WrapWidth = _MaxLength * (_TileWidth + 4) + 20;
        _BorderTopWidth = Math.round(_TileWidth * Math.sqrt(1 / 12));
        _TileHeight = Math.round(Math.sqrt(Math.pow(_TileWidth, 2) / 3));
        var result = {
            TileList: arr,
            TileWidth: _TileWidth,
            TileHeight: _TileHeight,
            MaxLength: _MaxLength,
            WrapWidth: _WrapWidth,
            BorderTopWidth: _BorderTopWidth
        };

        return result;
    }//end getTilesArr

    //获取最大边长
    function getMinLines(sum, lines) {
        if (!lines) lines = 2;
        var _center_max = lines * 2 - 1;//中间最长 块数
        //标准容器内最大盛放数
        var _tiles_max = ((lines + _center_max) * lines) - _center_max;

        //盛不下时扩大一圈
        if (_tiles_max < sum) {

            lines = lines + 1;
            return getMinLines(sum, lines);
        }

        return lines;
    }

    //去重
    function unique(arr) {
        var temp = [];
        for (var i = 0; i < arr.length; i++) {
            if (temp.indexOf(arr[i]) == -1) {
                temp.push(arr[i]);
            }
        }

        return temp;
    }

    var init = function (o, opts) {
        var _panel = $(o);

        var tileObj = getTilesArr(opts);

        var tileArr = tileObj.TileList,
            WrapWidth = tileObj.WrapWidth,
            TileWidth = tileObj.TileWidth,
            TileHeight = tileObj.TileHeight,
            MaxLength = tileObj.MaxLength,
            BorderTopWidth = tileObj.BorderTopWidth;
        _panel.css({ width: WrapWidth + 'px', 'padding-top': TileHeight / 2 + 'px' });

        var tileMatrix = [];

        var backgroundImg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyM3B4IiB2aWV3Qm94PSIwIDAgMjAgMjMiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ5ICg1MTAwMikgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+57u/6ImyIGNvcHkgMjY0PC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggZD0iTTAsNy40ODU0ODcxMyBMMCwxNS41MTQ1MTI5IEM2LjA4MzExMTI5ZS0xNiwxNi41ODgyMTY4IDAuNTczODE2MjYzLDE3LjU4MDA1NyAxLjUwNDYyNDgxLDE4LjExNTI1MzcgTDguNTA0NzMwNTgsMjIuMTQwMTc3OCBDOS40MzA1OTAzMSwyMi42NzI1MjkgMTAuNTY5NjU0OSwyMi42NzI1MjI5IDExLjQ5NTUwODksMjIuMTQwMTYxNyBMMTguNDk1NDAzMSwxOC4xMTUyNTkyIEMxOS40MjYxOTU5LDE3LjU4MDA1ODIgMjAsMTYuNTg4MjI2OCAyMCwxNS41MTQ1MzQ0IEwyMCw3LjQ4NTI1NTE3IEMyMCw2LjQxMTU0MjgxIDE5LjQyNjE3NDgsNS40MTk2OTYxNCAxOC40OTUzNTQ3LDQuODg0NTAyNTMgTDExLjQ5NTQ5MjcsMC44NTk3OTE5MjIgQzEwLjU2OTY0NjEsMC4zMjc0NTc4OTcgOS40MzA2MDUyMywwLjMyNzQ2MjM3OCA4LjUwNDc2MjgsMC44NTk4MDM2ODkgTDEuNTA0NjI0ODEsNC44ODQ3NDYyNyBDMC41NzM4MTYyNjMsNS40MTk5NDMgLTYuMDgzMTExMjllLTE2LDYuNDExNzgzMjIgMCw3LjQ4NTQ4NzEzIFoiIGlkPSJwYXRoLTEiPjwvcGF0aD4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSI26L655b2iIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i5YyX5Lqs5pWw5o2u5Lit5b+DLS0t5Yy65Z+f5bGV56S65Zu+IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzY0LjAwMDAwMCwgLTM0OC4wMDAwMDApIj4KICAgICAgICAgICAgPGcgaWQ9Iue7v+iJsiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzY0LjAwMDAwMCwgMzQ4LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPGcgaWQ9IlBhdGgiPgogICAgICAgICAgICAgICAgICAgIDx1c2UgZmlsbC1vcGFjaXR5PSIwLjQ1IiBmaWxsPSIjM0RDMDBDIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIHN0cm9rZT0iIzNEQzAwQyIgc3Ryb2tlLXdpZHRoPSIxIiBkPSJNMC41LDcuNDg1NDg3MTMgTDAuNSwxNS41MTQ1MTI5IEMwLjUsMTYuNDA5MjY2MSAwLjk3ODE4MDIxOSwxNy4yMzU3OTk2IDEuNzUzODU0MDEsMTcuNjgxNzk2OSBMOC43NTM5NTk3OCwyMS43MDY3MjEgQzkuNTI1NTA5NTUsMjIuMTUwMzQ3IDEwLjQ3NDczMDEsMjIuMTUwMzQxOSAxMS4yNDYyNzUxLDIxLjcwNjcwNzYgTDE4LjI0NjE2OTMsMTcuNjgxODA1IEMxOS4wMjE4MywxNy4yMzU4MDQyIDE5LjUsMTYuNDA5Mjc4IDE5LjUsMTUuNTE0NTM0NCBMMTkuNSw3LjQ4NTI1NTE3IEMxOS41LDYuNTkwNDk0ODcgMTkuMDIxODEyMyw1Ljc2Mzk1NTk4IDE4LjI0NjEyODksNS4zMTc5NjEzIEwxMS4yNDYyNjY5LDEuMjkzMjUwNjkgQzEwLjQ3NDcyODEsMC44NDk2MzkwMDYgOS41MjU1MjczNSwwLjg0OTY0Mjc0MSA4Ljc1Mzk5MTk5LDEuMjkzMjYwNSBMMS43NTM4NTQwMSw1LjMxODIwMzA4IEMwLjk3ODE4MDIxOSw1Ljc2NDIwMDM1IDAuNSw2LjU5MDczMzg3IDAuNSw3LjQ4NTQ4NzEzIFoiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+';


        for (var i = 0, len = tileArr.length; i < len; i++) {

            var tile = tileArr[i];

            tileMatrix.push(`<div style="height:${TileHeight * 1.5}px" class="tile-line">`);

            for (var j = 0, jen = tile.tiles.length; j < jen; j++) {

                var t = tile.tiles[j];

                var left = TileWidth * j + ( MaxLength - jen) * TileWidth / 2;

                left = left + j;
                tileMatrix.push(`
                <a class="${!t.show ? 'sexangle sexangle-hide' : 'sexangle'}"
                    data-id=${j}
                    style=" 
                        width:${TileWidth}px;
                        height:${TileHeight}px;
                        background-color :none;
                        position:absolute;
                        left:${left}px;
                        top:0px;
                    "
                    href="javascript:void(0);">
                         <span
                        style="
                            border-left-width : ${(TileWidth / 2)}px;
                            border-right-width : ${(TileWidth / 2)}px;
                            border-bottom-width : ${BorderTopWidth}px;
                            top:${(-BorderTopWidth)}px;
                            border-color : none;
                        "></span>
                        <span 
                        style="
                            border-left-width : ${(TileWidth / 2)}px;
                            border-right-width : ${(TileWidth / 2)}px;
                            border-top-width : ${BorderTopWidth}px;
                            bottom:${(-BorderTopWidth)}px;
                            border-color : none;
                        "></span>
                        <img src= ${backgroundImg}
                            style="
                                position: relative;
                                width:100%;
                                margin-top : ${-(TileWidth / 2)}px
                            " 
                        />
                </a>
                `);
            }

            tileMatrix.push(`</div>`);

        }

        _panel.html(tileMatrix.join(''));
    };

    $.fn[_pluginName] = function (options) {

        var options = $.extend(defaults, options);
        return this.each(function () {

            init(this, options);
        });
    }
})(jQuery, window, document);

2.HTML

<div class="wrap"></div>

3.调用

$(function () {

        var Hosts = [];
        for (let i = 0; i < 7; i++) {
            Hosts.push({
                "hostName": "wang-mac",
                "hostId": "23",
                "cpuPercentage": "8%",
                "ioPercentage": "16%",
                "color": '#FF4602'
            });
        }

        //链式调用测试
        $(".wrap").css({  }).jqHoneycomb({
            Hosts: Hosts,
            MaxWidth:560
        });
    })

4.大量数据情况