网络攻击流量图(中国/全球)echarts effectScatter配置项内容和展示

网络攻击流量图,可切换中国和全球流量走势。@idhyt

配置项如下
              var countMax = 2000
        var randomInt = function(min = 0, max = 1000) {
            var num = Math.random() * (max - min) + min
            return parseInt(num, 10)
        }

        var geoCoordMap = {
            "江苏": [118.8062, 31.9208],
            '黑龙江': [127.9688, 45.368],
            '内蒙古': [110.3467, 41.4899],
            "吉林": [125.8154, 44.2584],
            '北京市': [116.4551, 40.2539],
            "辽宁": [123.1238, 42.1216],
            "河北": [114.4995, 38.1006],
            "天津": [117.4219, 39.4189],
            "山西": [112.3352, 37.9413],
            "陕西": [109.1162, 34.2004],
            "甘肃": [103.5901, 36.3043],
            "宁夏": [106.3586, 38.1775],
            "青海": [101.4038, 36.8207],
            "新疆": [87.9236, 43.5883],
            "四川": [103.9526, 30.7617],
            "重庆": [108.384366, 30.439702],
            "山东": [117.1582, 36.8701],
            "河南": [113.4668, 34.6234],
            "安徽": [117.29, 32.0581],
            "湖北": [114.3896, 30.6628],
            "浙江": [119.5313, 29.8773],
            "福建": [119.4543, 25.9222],
            "江西": [116.0046, 28.6633],
            "湖南": [113.0823, 28.2568],
            "贵州": [106.6992, 26.7682],
            "云南": [102.9199, 25.4663],
            "广东": [113.12244, 23.009505],
            "广西": [108.479, 23.1152],
            "海南": [110.3893, 19.8516],
            '上海': [121.4648, 31.2891],
            "西藏": [91.11, 29.97],
            '尼日利亚': [-4.388361, 11.186148],
            '美国洛杉矶': [-118.24311, 34.052713],
            '香港邦泰': [114.195466, 22.282751],
            '美国芝加哥': [-87.801833, 41.870975],
            '加纳库马西': [-4.62829, 7.72415],
            '英国曼彻斯特': [-1.657222, 51.886863],
            '德国汉堡': [10.01959, 54.38474],
            '哈萨克斯坦阿拉木图': [45.326912, 41.101891],
            '俄罗斯伊尔库茨克': [89.116876, 67.757906],
            '巴西': [-48.678945, -10.493623],
            '埃及达米埃塔': [31.815593, 31.418032],
            '西班牙巴塞罗纳': [2.175129, 41.385064],
            '柬埔寨金边': [104.88659, 11.545469],
            '意大利米兰': [9.189948, 45.46623],
            '乌拉圭蒙得维的亚': [-56.162231, -34.901113],
            '莫桑比克马普托': [32.608571, -25.893473],
            '阿尔及利亚阿尔及尔': [3.054275, 36.753027],
            '阿联酋迪拜': [55.269441, 25.204514],
            '匈牙利布达佩斯': [17.108519, 48.179162],
            '澳大利亚悉尼': [150.993137, -33.675509],
            '美国加州': [-121.910642, 41.38028],
            '澳大利亚墨尔本': [144.999416, -37.781726],
            '墨西哥': [-99.094092, 19.365711],
            '加拿大温哥华': [-123.023921, 49.311753]
        }

        // points 所有攻击流量, 由多个攻击向量组成(from -> to), from == 1, to >= 1
        var points = [{
                'from': {
                    'name': '北京市',
                },
                'to': [{
                    'name': '福建',
                    'count': randomInt()
                }, {
                    'name': '江西',
                    'count': randomInt()
                }, {
                    'name': '湖南',
                    'count': randomInt()
                }, {
                    'name': '贵州',
                    'count': randomInt()
                }, {
                    'name': '云南',
                    'count': randomInt()
                }, {
                    'name': '广东',
                    'count': randomInt()
                }, {
                    'name': '广西',
                    'count': randomInt()
                }, {
                    'name': '海南',
                    'count': randomInt()
                }, {
                    'name': '上海',
                    'count': randomInt()
                }, {
                    'name': '西藏',
                    'count': randomInt()
                }, {
                    'name': '北京市',
                    'count': randomInt()
                }, {
                    'name': '辽宁',
                    'count': randomInt()
                }, {
                    'name': '河北',
                    'count': randomInt()
                }, {
                    'name': '天津',
                    'count': randomInt()
                }, {
                    'name': '四川',
                    'count': randomInt()
                }]
            },

            {
                'from': {
                    'name': '四川',
                },
                'to': [{
                    'name': '江苏',
                    'count': randomInt()
                }, {
                    'name': '黑龙江',
                    'count': randomInt()
                }, {
                    'name': '内蒙古',
                    'count': randomInt()
                }, {
                    'name': '吉林',
                    'count': randomInt()
                }, {
                    'name': '北京市',
                    'count': randomInt()
                }, {
                    'name': '辽宁',
                    'count': randomInt()
                }, {
                    'name': '河北',
                    'count': randomInt()
                }, {
                    'name': '天津',
                    'count': randomInt()
                }, {
                    'name': '山西',
                    'count': randomInt()
                }, {
                    'name': '陕西',
                    'count': randomInt()
                }, {
                    'name': '甘肃',
                    'count': randomInt()
                }, {
                    'name': '宁夏',
                    'count': randomInt()
                }, {
                    'name': '青海',
                    'count': randomInt()
                }, {
                    'name': '新疆',
                    'count': randomInt()
                }, {
                    'name': '重庆',
                    'count': randomInt()
                }, {
                    'name': '山东',
                    'count': randomInt()
                }, {
                    'name': '河南',
                    'count': randomInt()
                }, {
                    'name': '安徽',
                    'count': randomInt()
                }, {
                    'name': '湖北',
                    'count': randomInt()
                }, {
                    'name': '浙江',
                    'count': randomInt()
                }]
            }
        ]

        /*
            获取每个散点坐标
            将所有的 from, to 中的coord收集
            value 值为 to 的所有count之和,例如 北京->新疆 100, 四川 -> 新疆 200, 则 新疆 value = 300
            返回数据: [
                { name: '北京', value: [116.4551, 40.2539, 1930] },
                { name: '浙江', value: [119.5313, 29.8773, 58] }
            ]
        */
        function getScatterData(data) {
            var res = []
            var coords = {}
            var values = {}

            for (var i = 0; i < data.length; i++) {
                var from_data = data[i].from
                var to_data = data[i].to
                // 将 from 先记录
                coords[from_data.name] = geoCoordMap[from_data.name]
                if (!values.hasOwnProperty(from_data.name)) {
                    values[from_data.name] = 0
                }


                // 遍历 to
                to_data.map(function(item) {
                    // 记录 value 如果存在 直接记录 数值相加
                    if (values.hasOwnProperty(item.name)) {
                        values[item.name] = values[item.name] + item.count
                    } else {
                        values[item.name] = item.count
                    }

                    // 记录 coord, 如果重复 就不记录了, 前提是保证 每个 name 只能对应唯一的 coord
                    if (!coords.hasOwnProperty(item.name)) {
                        coords[item.name] = geoCoordMap[item.name]
                    }
                })
            }

            // 拼装数据
            for (var n in coords) {
                res.push({
                    name: n,
                    value: coords[n].concat(values[n])
                })
            }

            return res

        }

        /*
            获取连线数据 连线方向 from -> to
            返回数据: [
                { coords: [ [116.4551, 40.2539], [119.5313, 29.8773] ], value: 510},
            ]
        */
        function getLinesData(data) {
            var res = []
            for (var i = 0; i < data.length; i++) {
                var dataItem = data[i]
                res = res.concat(
                    dataItem.to.map(function(item) {
                        return {
                            // name: item.name,
                            coords: [geoCoordMap[dataItem.from.name], geoCoordMap[item.name], item.name, item.count],
                            value: item.count
                        }
                    })
                )
            }
            return res
        }

        option = {
            backgroundColor: '#013954',
            title: {
                text: '网络攻击流量图(中国/全球)',
                subtext: '@idhyt',
                x: 'center',
                top: 20,
                textStyle: {
                    color: "#fff"
                },
            },
            geo: {
                map: 'china',
                show: true,
                aspectScale: 0.75, //长宽比
                layoutCenter: ["50%", "40%"], //地图位置
                layoutSize: "80%",
                zoom: 1.1,
                roam: true, //是否允许缩放
                label: {
                    normal: {
                        // 是否显示省份名称
                        show: false,
                        textStyle: {
                            color: '#1DE9B6'
                        }
                    },
                    emphasis: {
                        textStyle: {
                            color: '#FFA07A' // 'rgb(183,185,14)'
                        }
                    }
                },
                itemStyle: {
                    normal: {
                        borderColor: 'rgb(147, 235, 248)',
                        borderWidth: 1,
                        areaColor: {
                            type: 'radial',
                            x: 0.5,
                            y: 0.5,
                            r: 0.8,
                            colorStops: [{
                                offset: 0,
                                color: '#09132c' // 0% 处的颜色
                            }, {
                                offset: 1,
                                color: '#274d68' // 100% 处的颜色
                            }],
                            globalCoord: true // 缺省为 false
                        },
                        shadowColor: 'rgb(58,115,192)',
                        shadowOffsetX: 5,
                        shadowOffsetY: 6
                    },
                    emphasis: {
                        // areaColor: '#2AB8FF',
                        areaColor: 'rgb(46,229,206)',
                        borderWidth: 0.1,
                        color: 'green',
                        label: {
                            show: true
                        }
                    }
                },
            },
            // 图例值控制 数值越大 颜色越深
            visualMap: {
                min: 0,
                max: countMax,
                top: '40%',
                right: 100,
                // bottom: 400,
                range: [0, countMax],
                show: true,
                calculable: true,
                // color: ["#0bc7f3"],
                textStyle: {
                    color: "#fff"
                },

            },
            // 提示信息
            tooltip: {
                trigger: "item",
                backgroundColor: "#1540a1",
                borderColor: "#FFFFCC",
                showDelay: 0,
                hideDelay: 0,
                enterable: true,
                transitionDuration: 0,
                extraCssText: "z-index:100",
                formatter: function(params, ticket, callback) {
                    // 散点提示信息
                    if (params.componentSubType === 'effectScatter') {
                        return "<span style='color:#fff;'>" + params.name + "</span><br/> 被攻击次数:" + params.value[2]
                    } else
                    if (params.componentSubType === 'lines') {
                        return "<span style='color:#fff;'>" + params.data.coords[2] + '</span><br/> be attacked:' + params.data.coords[3]
                    }
                }
            },
            toolbox: {
                x: 'center',
                top: 80,
                feature: {
                    myTool1: {
                        show: true,
                        title: 'China',
                        icon: 'path://M828.823 847.837l63.619 0 0-64.263-63.619 0 0 64.263zM510.741 912.091l127.23 0 0 64.268-127.23 0 0-64.268zM1008.606 153.874l-123.609-106.174c-9.098-7.766-21.691-9.837-32.765-5.203l-95.677 39.911-77.1 48.831c-10.186 6.556-15.85 18.329-14.575 30.402l9.609 94.608-89.001 61.763-104.905 12.524-83.851-46.016-52.098-102.629c-7.891-15.553-26.654-21.852-42.239-14.204l-113.053 55.718c-10.939 5.398-17.875 16.587-17.875 28.87l0 42.147-37.728 37.149-42.878 0c-8.204 0-16.159 3.21-22.074 9.001l-57.257 55.716c-12.974 12.658-12.974 33.612 0 46.27l50.198 48.849 28.818 137.906c1.524 7.276 5.474 13.829 11.262 18.449l104.391 84.514c5.661 4.56 12.665 7.063 19.914 7.063l115.024 0 0 69.921c0 17.743 14.246 32.14 31.802 32.14l128.062 0 57.959 39.851c10.052 6.931 23.09 7.439 33.653 1.349l78.75-45.443 108.661-41.321c5.788-2.189 10.746-6.103 14.444-11.113l68.384-94.862c3.947-5.534 6.109-12.148 6.109-18.899l0-93.573c0-8.684-3.498-16.976-9.605-23.007l-39.95-39.204 50.571-33.67c4.708-3.091 8.463-7.394 11.01-12.465l35.498-71.541 89.765-63.11c8.522-6.029 13.615-15.852 13.615-26.353l0-129.687c0-9.431-4.138-18.385-11.262-24.475l0 0zM956.243 291.195l-82.762 58.314c-4.319 3.075-7.884 7.185-10.238 11.954l-35.249 71.06-76.719 50.845c-16.992 11.306-19.281 35.531-4.709 49.867l58.716 57.712 0 69.532-56.685 78.682-104.261 40.091-65.907 37.659-49.687-34.18c-5.28-3.675-11.513-5.593-17.939-5.593l-106.114 0 0-69.923c0-17.743-14.249-32.14-31.81-32.14l-135.626 0-86.841-70.252-28.431-136.362c-1.342-6.315-4.454-12.09-9.103-16.528l-33.395-32.577 29.198-23.591 38.107 0c8.271 0 16.286-3.267 22.209-9.12l56.549-55.716c6.045-5.985 9.545-14.266 9.545-22.949l-5.284-10.079 72.521-58.554 42.309 83.347c2.926 5.728 7.505 10.467 13.105 13.557l101.405 55.733c5.789 3.089 12.404 4.364 18.961 3.583l122.647-14.695c5.09-0.646 9.989-2.462 14.249-5.414l111.073-76.985c9.613-6.691 14.826-18.058 13.617-29.759l-9.539-93.766 55.601-35.666 72.778-29.952 97.711 83.93 0 97.936-0.001 0zM956.243 291.195z',
                        onclick: function(e) {
                            regionSwitch(e.scheduler.ecInstance, r = 0)
                        }
                    },
                    myTool2: {
                        show: true,
                        title: 'World',
                        icon: 'path://M496 0c-273.952 0-496 222.048-496 496s222.048 496 496 496 496-222.048 496-496-222.048-496-496-496zM927.2 480l-191.872 0c-1.76-70.88-14.368-138.592-36.736-200.576 43.2-18.016 83.136-41.984 119.552-70.304 64.736 72.672 105.216 167.04 109.056 270.88zM478.304 927.104c-53.184-44.288-97.792-101.792-130.432-168.576 41.888-13.088 86.272-20.256 132.128-21.728l0 190.368c-0.576 0-1.12-0.032-1.696-0.064zM513.632 64.896c60.352 50.24 109.6 117.536 142.912 196.032-45.632 15.584-94.112 24.64-144.576 26.24l0-222.368c0.608 0.032 1.12 0.064 1.664 0.096zM566.944 70.336c88.32 14.688 167.552 55.936 229.248 115.648-33.504 25.696-70.112 47.456-109.696 63.936-29.12-69.024-69.984-130.048-119.552-179.584zM480 64.8l0 222.368c-50.464-1.632-98.976-10.656-144.576-26.24 33.312-78.496 82.56-145.792 142.912-196.032 0.576-0.032 1.088-0.064 1.664-0.096zM305.472 249.952c-39.52-16.48-76.16-38.24-109.664-63.936 61.664-59.712 140.928-100.96 229.248-115.648-49.6 49.504-90.432 110.528-119.584 179.584zM323.36 290.432c49.344 17.12 101.92 27.104 156.64 28.768l0 160.8-191.328 0c1.728-67.008 13.6-131.04 34.688-189.568zM480 512l0 192.8c-50.464 1.536-99.264 9.792-145.248 24.608-27.712-65.984-44.064-139.488-46.08-217.408l191.328 0zM425.056 921.664c-79.136-13.152-151.008-47.616-209.44-97.664 31.52-21.856 65.6-40.352 102.016-54.4 27.904 57.856 64.416 109.216 107.424 152.064zM512 927.2l0-190.368c45.824 1.472 90.24 8.64 132.128 21.728-32.672 66.784-77.248 124.288-130.432 168.576-0.544 0-1.12 0.032-1.696 0.064zM674.368 769.6c36.384 14.048 70.432 32.576 102.016 54.4-58.432 50.016-130.304 84.512-209.44 97.664 43.008-42.848 79.488-94.208 107.424-152.064zM657.248 729.408c-46.016-14.816-94.816-23.072-145.248-24.608l0-192.8 191.328 0c-2.016 77.92-18.4 151.424-46.08 217.408zM512 480l0-160.8c54.688-1.664 107.264-11.616 156.64-28.736 21.056 58.528 32.928 122.56 34.688 189.568l-191.328 0zM173.888 209.12c36.416 28.32 76.352 52.288 119.52 70.304-22.368 61.984-34.976 129.696-36.736 200.576l-191.872 0c3.84-103.84 44.32-198.208 109.088-270.88zM64.8 512l191.872 0c1.984 81.76 19.072 158.976 48.096 228.384-40.544 15.808-78.336 36.864-113.216 61.792-75.136-74.784-122.56-177.024-126.752-290.176zM800.448 802.144c-34.88-24.896-72.672-45.984-113.248-61.792 29.056-69.408 46.112-146.624 48.128-228.384l191.872 0c-4.192 113.184-51.648 215.424-126.752 290.176z',
                        onclick: function(e) {
                            regionSwitch(e.scheduler.ecInstance, r = 1)
                        }
                    }
                },
                iconStyle: {
                    normal: {
                        borderColor: '#fff'
                    },
                    emphasis: {
                        borderColor: '#b1e4ff'
                    }
                },
            },
            series: [{
                    type: 'effectScatter',
                    coordinateSystem: 'geo',
                    showEffectOn: 'render',
                    zlevel: 1,
                    // 涟漪特效
                    rippleEffect: {
                        period: 15, //动画时间,值越小速度越快
                        scale: 4, //波纹圆环最大限制,值越大波纹越大
                        brushType: 'fill' //波纹绘制方式 stroke, fill
                    },
                    // hoverAnimation: true,
                    label: {
                        normal: {
                            // 是否显示name
                            show: true,
                            formatter: '{b}', //圆环显示文字
                            position: 'top', //显示位置
                            offset: [5, 0], //偏移设置
                            color: '#1DE9B6'
                        },
                        emphasis: {
                            show: true
                        }
                    },
                    // symbolSize: 12,
                    symbol: "circle",
                    symbolSize: function(val) {
                        if (!val[2]) return 6
                        return 6 + val[2] / (countMax / 10) //圆环大小
                    },
                    itemStyle: {
                        normal: {
                            show: true,
                            color: '#1DE9B6'
                                /* function (params) { //随机颜色
                                                               // return "#"+("00000"+((params.data.value[2]*16777215+0.5)>>0).toString(16)).slice(-6);
                                                               return "#"+("00000"+((Math.random()*16777215+0.5)>>0).toString(16)).slice(-6);
                                                           }*/
                                ,

                            // shadowBlur: 10,
                            // shadowColor: '#333'
                        }
                    },

                    data: getScatterData(points)
                },
                {
                    type: 'lines',
                    zlevel: 2,
                    effect: {
                        show: true,
                        period: 4, //箭头指向速度,值越小速度越快
                        trailLength: 0.2, //特效尾迹长度[0,1]值越大,尾迹越长重
                        symbol: 'arrow', //箭头图标 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
                        symbolSize: 5, //图标大小
                    },
                    lineStyle: {
                        normal: {
                            width: 1, //线条宽度
                            opacity: 0.1, //0.1, //尾迹线条透明度
                            curveness: 0.3 //尾迹线条曲直度
                        }
                    },
                    data: getLinesData(points)
                }
            ]
        };

        /*
            0: China
            1: World
        */
        function regionSwitch(ecIns, r = 0) {
            var op = JSON.parse(JSON.stringify(option))
            if (r === 0) {
                op.geo.map = 'china'
                op.series[0].data = getScatterData(points)
                op.series[1].data = getLinesData(points)

            } else if (r === 1) {
                op.geo.map = 'world'
                // points 所有攻击流量, 由多个攻击向量组成(from -> to), from == 1, to >= 1
                var worldPoints = [{
                    'from': {
                        'name': '上海',
                    },
                    'to': [{
                            'name': '加拿大温哥华',
                            'count': randomInt()
                        }, {
                            'name': '墨西哥',
                            'count': randomInt()
                        }, {
                            'name': '澳大利亚墨尔本',
                            'count': randomInt()
                        },
                        {
                            'name': '美国加州',
                            'count': randomInt()
                        }, {
                            'name': '澳大利亚悉尼',
                            'count': randomInt()
                        }, {
                            'name': '匈牙利布达佩斯',
                            'count': randomInt()
                        }, {
                            'name': '阿联酋迪拜',
                            'count': randomInt()
                        }, {
                            'name': '阿尔及利亚阿尔及尔',
                            'count': randomInt()
                        },
                        {
                            'name': '莫桑比克马普托',
                            'count': randomInt()
                        }, {
                            'name': '美国洛杉矶',
                            'count': randomInt()
                        }, {
                            'name': '香港邦泰',
                            'count': randomInt()
                        }, {
                            'name': '美国芝加哥',
                            'count': randomInt()
                        }, {
                            'name': '加纳库马西',
                            'count': randomInt()
                        }, {
                            'name': '英国曼彻斯特',
                            'count': randomInt()
                        }, {
                            'name': '德国汉堡',
                            'count': randomInt()
                        }, {
                            'name': '哈萨克斯坦阿拉木图',
                            'count': randomInt()
                        }, {
                            'name': '俄罗斯伊尔库茨克',
                            'count': randomInt()
                        }, {
                            'name': '巴西',
                            'count': randomInt()
                        }, {
                            'name': '埃及达米埃塔',
                            'count': randomInt()
                        }, {
                            'name': '西班牙巴塞罗纳',
                            'count': randomInt()
                        }, {
                            'name': '柬埔寨金边',
                            'count': randomInt()
                        }, {
                            'name': '意大利米兰',
                            'count': randomInt()
                        }, {
                            'name': '乌拉圭蒙得维的亚',
                            'count': randomInt()
                        }
                    ]
                }]
                op.series[0].data = getScatterData(worldPoints)
                op.series[1].data = getLinesData(worldPoints)
            }

            ecIns.setOption(op)
        }
        /*
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <script src="echarts.min.js"></script>
            <script src="world.js"></script>
            <script src="china.js"></script>

        </head>
        <body>
        	<div id="maps" style="width: '100%'; height:1000px;"></div>
        	<script>
        		var maps = echarts.init(document.getElementById('maps'));
        		maps.setOption(option);
        	</script>
        </body>
        </html>
        */
    
截图如下