日间照料设施热力图2021echarts 配置项内容和展示

配置项如下
      var option = {
    bmap: {
        center: [121.4693, 31.2],
        zoom: 10,
        roam: true,
        enableMapClick: false,
        mapStyle: {
            styleJson: [
                {
                    featureType: 'all',
                    elementType: 'all',
                    stylers: {
                        lightness: 15,
                        saturation: -50,
                    },
                },
                {
                    featureType: 'highway',
                    elementType: 'geometry.fill',
                    stylers: {
                        color: '#ffffff',
                    },
                },
                {
                    featureType: 'poi',
                    elementType: 'labels.icon',
                    stylers: {
                        visibility: 'off',
                    },
                },
                {
                    featureType: 'road',
                    elementType: 'labels',
                    stylers: {
                        visibility: 'off',
                    },
                },
            ],
        },
    },
    title: {
        x: 'center',
        text: '上海日间照料设施热力图',
        subtext: '',
        textStyle: {
            color: '#696969',
            fontSize: 25,
        },
    },
};

myChart.setOption(option);

setTimeout(init, 0);

function init() {
    initMap();
    initMapv();
}

function getMap() {
    return myChart.getModel().getComponent('bmap').getBMap();
}

function initMap() {
    var top_left_navigation = new BMap.NavigationControl({
        type: BMAP_NAVIGATION_CONTROL_SMALL,
    });
    var scale = new BMap.ScaleControl({
        offset: new BMap.Size(100, 50),
    });
    var map = getMap();
    map.addControl(top_left_navigation);
    map.addControl(scale);
    map.disableDoubleClickZoom();
    return map;
}

function initMapv() {
    var map = getMap();
    var data = [];
    var randomCount = points.length;

    // 构造数据
    while (randomCount--) {
        var cityCenter = points[randomCount];
        data.push({
            geometry: {
                type: 'Point',
                coordinates: [cityCenter[0], cityCenter[1]],
            },
            count: cityCenter[2],
        });
    }

    var dataSet = new mapv.DataSet(data);
    //console.log(dataSet)

    var options = {
        fillStyle: '#DC143C',
        strokeStyle: 'black', // 描边颜色
        lineWidth: 1,
        //shadowColor: 'white',
        //shadowBlur: 1,
        size: 15,
        globalAlpha: 1,
        gradient: { 0.25: 'rgb(0,0,255)', 0.5: 'rgb(0,255,0)', 0.75: 'yellow', 1.0: 'rgb(255,0,0)' },
        label: {
            show: true,
            fillStyle: 'white',
            average: false,
            //shadowColor: 'black',
            // font: '20px Arial',
            //shadowBlur: 10,
        },
        max: 5,

        draw: 'heatmap',
        methods: {
            // 一些事件回调函数
            click: function (item) {
                // 点击事件,返回对应点击元素的对象值
                console.log(item);
            },
        },
    };

    var mapvLayer = new mapv.baiduMapLayer(map, dataSet, options);
}

//---------------------------------------------

var points = [
    [121.375419598552, 31.794989911741, 1],
    [121.472057510501, 31.2489823712144, 1],
    [121.437170197274, 31.197221012831, 1],
    [121.430838311226, 31.1995756745814, 1],
    [121.485709607751, 31.2200419174149, 1],
    [121.436097530665, 31.2214746217424, 1],
    [121.379664073222, 31.0383065448668, 1],
    [121.374151191172, 31.0381839483837, 1],
    [121.37691276197, 31.034697073159, 1],
    [121.563577671756, 31.1984755660157, 1],
    [121.375415556177, 31.1200161877323, 1],
    [121.38172875747, 31.101746204597, 1],
    [121.49688005159, 31.2899050069843, 1],
    [121.444127519551, 31.2147024472189, 1],
    [121.668695686533, 31.2141451212896, 1],
    [121.395045956995, 30.8237645782608, 1],
    [121.395362969009, 31.3439578768374, 1],
    [121.546845754276, 30.8842458030581, 1],
    [121.120384735453, 30.9720784777697, 1],
    [121.308435164708, 31.4394007535013, 1],
    [121.248022360279, 30.8329210612252, 1],
    [121.057075037687, 31.1142535832699, 1],
    [121.379243125463, 31.2217764568648, 1],
    [121.651424685137, 30.9171331001925, 1],
    [121.494601809579, 31.2851591184254, 1],
    [121.492811150732, 30.8453967825606, 1],
    [121.381213258565, 31.1968148054537, 1],
    [121.438395306329, 31.2031216872021, 1],
    [121.770161180326, 30.9152771486046, 1],
    [121.518296870355, 31.1307312314605, 1],
    [121.534253846621, 31.3088182399269, 1],
    [121.42238579536, 31.2957851787363, 1],
    [121.341453409592, 31.3873787161201, 1],
    [121.34682024603, 31.4381201995952, 1],
    [121.342295571007, 31.4087056190161, 1],
    [121.424615389636, 31.2866341587868, 1],
    [121.43136272222, 31.3520811287837, 1],
    [121.342263232009, 31.3942647782779, 1],
    [121.506260604183, 31.3956055519956, 1],
    [121.621167689458, 31.5726935728513, 1],
    [121.43204213044, 31.6554855095312, 1],
    [121.225376158322, 31.7738289250939, 1],
    [121.583184098596, 31.6254814759569, 1],
    [121.284987013082, 31.8452230479431, 1],
    [121.032870465212, 31.0766650624522, 1],
    [121.604561613801, 30.9695740561199, 1],
    [121.610006692649, 30.9723573792117, 1],
    [121.463270284205, 30.914150563144, 1],
    [121.561072038977, 30.832646865634, 1],
    [121.483703590488, 30.8804019388552, 1],
    [121.40302569467, 30.8993422904721, 1],
    [121.044938750586, 31.019338930526, 1],
    [121.044502802922, 31.0534559570206, 1],
    [121.479310427392, 31.2931613917834, 1],
    [121.476285468027, 31.2905118118257, 1],
    [121.471994088335, 31.3031541756929, 1],
    [121.494689687214, 31.2906376668244, 1],
    [121.164345022364, 31.3005464092083, 1],
    [121.500650026019, 31.2160911638612, 1],
    [121.50207600427, 31.2115729354441, 1],
    [121.479210535819, 31.2207000383118, 1],
    [121.482657962875, 31.2185713484321, 1],
    [121.481265230012, 31.2232404750637, 1],
    [121.480282304123, 31.2453202079541, 1],
    [121.488468719439, 31.2378077475065, 1],
    [121.475632764634, 31.2434464806782, 1],
    [121.485418006554, 31.2434306577266, 1],
    [121.473435778848, 31.2439168456352, 1],
    [121.504875842883, 31.2273413445795, 1],
    [121.497159847705, 31.2361840048573, 1],
    [121.495726062281, 31.2264033019693, 1],
    [121.494890291411, 31.2222521655822, 1],
    [121.414345601724, 31.2526620846039, 1],
    [121.50322709295, 31.2255243851069, 1],
    [121.204917543431, 31.4115869040505, 1],
    [121.253275471241, 31.3714144166778, 1],
    [121.257483493572, 31.3940774443095, 1],
    [121.024437891729, 31.020110456019, 1],
    [121.253501574737, 31.3850711747581, 1],
    [121.334384194381, 31.2643521264968, 1],
    [121.252619985795, 31.4110252270937, 1],
    [121.28926805777, 31.3372830466235, 1],
    [121.298705296136, 31.3839425841505, 1],
    [121.314514305314, 31.2945215088285, 1],
    [121.184240405341, 31.3593950950005, 1],
    [121.270863116346, 31.3905777096785, 1],
    [121.387312444859, 30.7994416476357, 1],
    [121.411092298489, 30.8038169539484, 1],
    [121.435572650755, 30.81607420021, 1],
    [121.081871636611, 30.8735964388165, 1],
    [121.041756413486, 30.9061526218124, 1],
    [121.344274987199, 30.8648402519372, 1],
    [121.385492657557, 30.8562889671341, 1],
    [121.342353253001, 30.8533347135566, 1],
    [121.283307710881, 30.7707834252285, 1],
    [121.320170126635, 30.7504341135338, 1],
    [121.319276043161, 30.7322718633636, 1],
    [121.255138287377, 30.7806307584895, 1],
    [121.202330501464, 30.8046750468687, 1],
    [121.1988845099, 30.797033014634, 1],
    [121.202442608195, 30.8047666513497, 1],
    [121.189066415151, 30.7861260452923, 1],
    [121.201393162783, 30.7932997224104, 1],
    [121.148241458809, 30.8074443173766, 1],
    [121.180994486177, 30.8313525463332, 1],
    [121.139000500197, 30.9484907187308, 1],
    [121.382612432279, 30.7668267563722, 1],
    [121.378580082573, 30.7732441036199, 1],
    [121.377416008887, 30.7700205938079, 1],
    [121.383019802149, 30.7388671946375, 1],
    [121.345429279236, 30.7803221990066, 1],
    [121.366414714628, 30.7428850092894, 1],
    [121.369571989004, 30.7920498302599, 1],
    [121.361590095395, 30.7527116388023, 1],
    [121.348389495926, 30.730469494733, 1],
    [121.515549239461, 31.267087455716, 1],
    [121.406671557413, 31.2425431788205, 1],
    [121.346871988428, 30.7214486811635, 1],
    [121.417718289761, 30.8009584991072, 1],
    [121.262529275621, 30.8523108924913, 1],
    [121.345376399584, 30.8903490992557, 1],
    [121.298857918242, 30.8581895517137, 1],
    [121.245877835535, 30.9171261294049, 1],
    [121.288679308339, 30.8964804341677, 1],
    [121.304621895547, 30.8849817059168, 1],
    [121.246720038273, 30.8993458042536, 1],
    [121.27192805124, 30.8784218823146, 1],
    [121.279863248233, 30.7893047989385, 1],
    [121.31688744881, 30.799486316, 1],
    [121.294759397556, 30.8103355897258, 1],
    [121.279024410548, 30.8126439587694, 1],
    [121.174711864102, 30.891798786, 1],
    [121.216118321448, 30.8978746761695, 1],
    [121.179200031091, 30.9127097225313, 1],
    [121.480162649829, 31.2049094302128, 1],
    [121.390833622797, 31.1513182382084, 1],
    [121.38929500512, 31.1771248279827, 1],
    [121.302127211315, 31.2106071314423, 1],
    [121.425933563141, 31.0123413735272, 1],
    [121.395340960524, 31.0288816661045, 1],
    [121.549489467392, 31.061476548605, 1],
    [121.536437806976, 31.1049495382507, 1],
    [121.509360004328, 31.0352118819347, 1],
    [121.479323093499, 31.050405326571, 1],
    [121.316921045436, 31.2195158003406, 1],
    [121.318340547803, 31.2143507294212, 1],
    [121.397648128871, 31.0676878395846, 1],
    [121.528365454003, 31.1940658493762, 1],
    [121.538872933553, 31.1493744070405, 1],
    [121.622184211973, 31.3380557594464, 1],
    [121.583783178541, 31.2940441471092, 1],
    [121.618422326786, 31.3033771681635, 1],
    [121.590800741185, 31.3533112733688, 1],
    [121.542931833576, 31.206883079096, 1],
    [121.5423303318, 31.1941812247261, 1],
    [121.574196766664, 31.2317276783339, 1],
    [121.9237855412, 30.8891158557756, 1],
    [121.692675592799, 31.2506322167193, 1],
    [121.530528753332, 31.2160875326289, 1],
    [121.523627970404, 31.2179132451884, 1],
    [121.826416060922, 30.9777199195254, 1],
    [121.522177207006, 31.2319240389101, 1],
    [121.531550935172, 31.2311124110338, 1],
    [121.531913940428, 31.2253816423621, 1],
    [121.525628227283, 31.2252695478528, 1],
    [121.527591294314, 31.2277853887939, 1],
    [121.530367148171, 31.2240141882577, 1],
    [121.54138962627, 31.2348142384663, 1],
    [121.628175338402, 31.2184193161849, 1],
    [121.633871795472, 31.1922055373932, 1],
    [121.502606274012, 31.1785212361064, 1],
    [121.413246704594, 31.2412992430896, 1],
    [121.446450269006, 31.2694750898218, 1],
    [121.42848484062, 31.2590263118045, 1],
    [121.40659115907, 31.2817770884334, 1],
    [121.392049119983, 31.2795252601165, 1],
    [121.418236682108, 31.2746644478903, 1],
    [121.447146957929, 31.2657140521941, 1],
    [121.428141508254, 31.2357748910452, 1],
    [121.40785462577, 31.2356455180786, 1],
    [121.421876456136, 31.2415179904949, 1],
    [121.421699489951, 31.2390235913603, 1],
    [121.420014178983, 31.2296612053128, 1],
    [121.404132407059, 31.2361859346352, 1],
    [121.440564695271, 31.250848772482, 1],
    [121.382859274955, 31.2496604484661, 1],
    [121.394763978895, 31.2498831124834, 1],
    [121.401353498964, 31.2443067821027, 1],
    [121.39476963822, 31.2652756669229, 1],
    [121.008257754816, 31.0463712637795, 1],
    [120.949014633992, 31.0653896143891, 1],
    [120.918683882041, 31.1145828111003, 1],
    [120.987158302895, 31.0598702885706, 1],
    [120.931198361151, 31.1216263674827, 1],
    [120.92432153154, 31.0412896522956, 1],
    [121.009104714979, 31.0649154151535, 1],
    [120.99028108234, 31.0305222608236, 1],
    [120.886904174082, 31.1253183775044, 1],
    [120.897765226681, 31.1305220475555, 1],
    [120.961300668621, 31.0579350065899, 1],
    [120.967505264779, 31.0775518694411, 1],
    [121.036627448347, 31.0653016108627, 1],
    [121.062234994367, 31.0471155963203, 1],
    [121.03370319442, 31.0402473448415, 1],
    [121.480162649829, 31.2049094302128, 1],
    [121.113978469708, 31.2196766179414, 1],
    [121.086190466724, 31.0542941805459, 1],
    [121.121454347823, 31.0772147461363, 1],
    [121.134156477565, 31.1623186414293, 1],
    [121.118824468612, 31.1406505063882, 1],
    [121.138964028993, 31.1733998641639, 1],
    [121.120042775697, 31.1278674919014, 1],
    [121.124064284652, 31.1516024812223, 1],
    [121.136256805678, 31.1475636618446, 1],
    [121.108635887518, 31.1409961337527, 1],
    [121.135380957806, 31.1587238822911, 1],
    [121.132088668111, 31.1333311444973, 1],
    [121.152629501564, 31.1109751274552, 1],
    [121.129551404199, 31.1608978890574, 1],
    [121.154726595777, 31.1672295773118, 1],
    [121.087834186146, 31.228626766515, 1],
    [121.103163462453, 31.2232529874666, 1],
    [121.151023960126, 31.2085959246922, 1],
    [121.142631990052, 31.2175851183092, 1],
    [121.11405987056, 31.2211414282816, 1],
    [121.139511245269, 31.1901113368624, 1],
    [121.076838028398, 31.2236730357229, 1],
    [121.300975853143, 31.2076861864258, 1],
    [121.277918506635, 31.1827289493722, 1],
    [121.277022985872, 31.1663688765891, 1],
    [121.602512101932, 31.2727755702417, 1],
    [121.488974847221, 31.226743904159, 1],
    [121.059785854224, 31.1123138543646, 1],
    [121.07634593664, 31.1497448807704, 1],
    [121.091342069162, 31.0492043984565, 1],
    [121.064543280205, 31.1546889232586, 1],
    [121.061715773782, 31.1030240726179, 1],
    [121.108326151778, 31.06862380293, 1],
    [121.099335461082, 31.0825762553713, 1],
    [121.05983085933, 30.9998046692764, 1],
    [121.054007144709, 30.9827729033733, 1],
    [121.41642365186, 31.0112877915958, 1],
    [121.432281978011, 31.0215818456505, 1],
    [121.714264569121, 31.1154329677245, 1],
    [121.516955177415, 31.1957735290498, 1],
    [121.71196409854, 31.0321246890163, 1],
    [121.769228836224, 31.1273812381417, 1],
    [121.385927886577, 30.998372097765, 1],
    [121.588213980638, 31.1090964718926, 1],
    [121.754668711552, 31.1834096978904, 1],
    [121.311102630818, 30.9872168442536, 1],
    [121.263142369132, 31.0108197772187, 1],
    [121.29298201207, 30.9708520912223, 1],
    [121.235276776805, 31.0643545013448, 1],
    [121.178928652996, 30.9365916029082, 1],
    [121.150497642927, 30.9621920783263, 1],
    [121.15021602415, 31.0095223194021, 1],
    [121.12676207576, 31.0355660965884, 1],
    [121.073868050721, 30.9368255406353, 1],
    [121.327718692937, 30.9380634628659, 1],
    [121.220758177204, 31.0128112876486, 1],
    [121.23934158678, 30.9999183941088, 1],
    [121.240136405699, 31.0248151394829, 1],
    [121.230748035153, 31.0223318447647, 1],
    [121.438462164513, 31.1671821564765, 1],
    [121.45759919169, 31.1879113647835, 1],
    [121.44119155172, 31.1398052477888, 1],
    [121.459914933465, 31.1745419704071, 1],
    [121.432270030548, 31.1688358576446, 1],
    [121.431877291379, 31.1799717669106, 1],
    [121.550941308757, 31.2998763093661, 1],
    [121.549851304851, 31.3051391672929, 1],
    [121.064620354818, 31.1116389281464, 1],
    [121.518778999905, 31.2743478725111, 1],
    [121.529326820559, 31.2908640133474, 1],
    [121.534455246716, 31.2638202369183, 1],
    [121.53034918206, 31.2679868936721, 1],
    [121.531196649767, 31.2633588378543, 1],
    [121.519207940786, 31.2830999074743, 1],
    [121.512397842698, 31.3110390626612, 1],
    [121.549065107869, 31.3321741654561, 1],
    [121.546425032891, 31.2997888728225, 1],
    [121.348252414505, 30.7910411408837, 1],
    [121.023059441924, 31.0195125475228, 1],
    [121.424990432187, 31.206821378658, 1],
    [121.409828382636, 31.2189619309826, 1],
    [121.432728580477, 31.2105988817801, 1],
    [121.423093390611, 31.220045733051, 1],
    [121.507927566362, 30.901671174411, 1],
    [121.741560395008, 30.8718961454877, 1],
    [121.447659835579, 31.2374483194911, 1],
    [121.447490166329, 31.2213221290604, 1],
    [121.463282231669, 31.2264020667823, 1],
    [121.453922483831, 31.2433531922992, 1],
    [121.463284567263, 31.2634062752071, 1],
    [121.4725849937, 31.2548368445297, 1],
    [121.441427013764, 31.2417186831477, 1],
    [121.370640520713, 31.2439959231379, 1],
    [121.276189250562, 31.1756022413165, 1],
    [121.046778395753, 31.0663510989682, 1],
    [121.339928535988, 31.4826387089352, 1],
    [121.334961535332, 31.4944150519686, 1],
    [121.470236463774, 31.2251912668969, 1],
    [121.305993967382, 31.3084988394188, 1],
    [121.501985814397, 31.2124126830597, 1],
    [121.556257660426, 31.2366538660035, 1],
    [121.743858615333, 30.9722700629453, 1],
    [121.597485977502, 31.0854585128238, 1],
    [121.491580202691, 31.2394840984479, 1],
    [121.406904488032, 31.2487703273591, 1],
    [121.439053943929, 31.2647159722648, 1],
    [121.429289790629, 31.2428617648029, 1],
    [121.539433981039, 31.0648129217634, 1],
    [121.535754783077, 31.069461074739, 1],
    [121.591183490298, 31.0982612452597, 1],
    [121.586555169684, 31.1206846390352, 1],
    [121.823464653016, 31.0050102493191, 1],
    [121.541148970224, 31.1676558305883, 1],
    [121.46446116782, 30.9207832439319, 1],
    [121.541648787409, 30.8984822397649, 1],
    [121.558590380175, 30.9544234954605, 1],
    [121.581741689439, 30.8919961277782, 1],
    [121.537433578634, 30.8831820731996, 1],
    [121.426192454789, 30.8364894853941, 1],
    [121.417982032259, 31.382778219422, 1],
    [121.39285975896, 31.4338598236383, 1],
    [121.486316132403, 31.4093095995078, 1],
    [121.561874405458, 31.2895215868333, 1],
    [121.548038703993, 31.2796401443325, 1],
    [121.537364588771, 31.2857423068127, 1],
    [121.535399055892, 31.3404923199862, 1],
    [121.465609741245, 31.2144699402378, 1],
    [121.460846476278, 31.1278205955403, 1],
    [121.399548803194, 31.2433519288546, 1],
    [121.641542765781, 31.322033620977, 1],
    [121.079477160156, 30.9802365660803, 1],
    [121.146212995137, 31.14593484213, 1],
    [121.111001664909, 31.1198557401632, 1],
    [121.481266963742, 31.3186713097602, 1],
    [121.464753296772, 31.2632414428369, 1],
    [121.476213339485, 31.3318880031294, 1],
    [121.539282740527, 31.3349685780551, 1],
    [121.545671040161, 31.6822352216097, 1],
    [121.625547827125, 31.6111090954425, 1],
    [121.459076400305, 31.2001939628681, 1],
    [121.581497170679, 31.2532768014976, 1],
    [121.540533630949, 31.3647628509238, 1],
    [121.623297540382, 31.5412844270225, 1],
    [121.486309574773, 31.3053964562606, 1],
    [121.400972617427, 31.3119713067526, 1],
    [121.910927180859, 30.9066412519196, 1],
    [121.570026527961, 31.6341980597286, 1],
    [121.441634685828, 31.0196374215824, 1],
    [121.474678854013, 31.0498352994843, 1],
    [121.453399972753, 31.0489458337771, 1],
    [121.473668260314, 31.0530201366201, 1],
    [121.449029087634, 31.0616459892676, 1],
    [121.469623460094, 31.04733201217, 1],
    [121.27861033842, 31.2443338052108, 1],
    [121.314397345937, 31.2268871852175, 1],
    [121.275878311093, 31.2480721456423, 1],
    [121.312106038072, 31.2196551550227, 1],
    [121.456016736704, 31.0515905387446, 1],
    [121.412954395981, 31.0605528557625, 1],
    [121.394714751753, 31.0274249345604, 1],
    [121.553095804692, 30.9327885818001, 1],
    [121.531743711534, 30.9089717380852, 1],
    [121.588725385965, 30.9291127249356, 1],
    [121.601003156184, 30.9225184224981, 1],
    [121.547546612235, 30.9903833641573, 1],
    [121.483269259774, 31.2937606449325, 1],
    [121.471781100099, 31.3054198580803, 1],
    [121.487190771156, 31.3026620109559, 1],
    [121.480154834571, 31.3083537551755, 1],
    [121.437044143452, 31.2684296347361, 1],
    [121.204555961737, 31.0109188190674, 1],
    [121.294634473802, 31.7487668885026, 1],
    [121.417334377342, 31.2484405262687, 1],
    [121.312878210709, 31.3047007676288, 1],
    [121.33095383513, 31.3095796752196, 1],
    [121.351336027829, 31.3877656641306, 1],
    [121.442010661718, 31.2744855371862, 1],
    [121.398376294419, 31.2406710053385, 1],
    [121.471408303312, 31.2778273644854, 1],
    [121.491794253623, 31.2741855406701, 1],
    [121.038713044249, 30.8613188495721, 1],
    [121.438135516375, 31.2339199620129, 1],
    [121.174462906814, 30.9014825449207, 1],
    [121.527736999468, 31.036138375936, 1],
    [121.311576397144, 30.8559643069335, 1],
    [121.084819922007, 30.9419531307207, 1],
    [121.400895991967, 31.1602571490414, 1],
    [121.400540622308, 31.160848524266, 1],
    [121.403017070938, 30.830168371375, 1],
    [121.410983064539, 31.009034762209, 1],
    [121.301735550112, 30.8161519684901, 1],
    [, , 1],
    [121.358020713485, 31.7202640796647, 1],
    [121.792200836522, 31.5421659584205, 1],
    [121.381396160754, 31.337172216529, 1],
    [121.359877655601, 31.3521386616133, 1],
    [121.246480090092, 31.4699070819214, 1],
    [121.408339351423, 30.9683069187347, 1],
    [121.516656490833, 30.8630765834352, 1],
    [121.588725385965, 30.9291127249356, 1],
    [121.534133383852, 30.9507171989043, 1],
    [121.533108237604, 30.9427308634825, 1],
    [121.585280743657, 30.9811869749117, 1],
    [121.473318190657, 31.220873978516, 1],
    [121.726743261536, 30.9448376798432, 1],
    [121.738803131584, 30.9027583236724, 1],
    [121.426449459996, 31.3694804766279, 1],
    [121.494757958433, 31.3309778453229, 1],
    [121.579013104419, 31.2618012972275, 1],
    [121.526916487215, 30.8803511873385, 1],
    [121.430939280765, 30.993488252327, 1],
    [121.432767332478, 31.2122743213375, 1],
    [121.35729493743, 31.2132188367737, 1],
    [121.3556811217, 31.215878833357, 1],
    [121.361658989139, 31.2188006574138, 1],
    [121.482768813774, 30.9912401807785, 1],
    [121.432259215848, 31.2281666731036, 1],
    [121.371720376462, 31.2528012355617, 1],
    [121.478660519525, 31.3143168757528, 1],
    [121.329786217628, 31.3412966616565, 1],
    [121.282716715686, 31.3561814500914, 1],
    [121.421068250669, 31.1517741546235, 1],
    [121.222569592299, 31.2733673673634, 1],
    [121.442880802655, 31.1706626014753, 1],
    [121.230771652503, 31.3122396124696, 1],
    [121.403120825224, 31.160778223814, 1],
    [121.745152469013, 31.0718674710274, 1],
    [121.452313112917, 31.2365490409351, 1],
    [121.515919700654, 31.2039321678747, 1],
    [121.423883899459, 31.0991677664041, 1],
    [121.337412831408, 31.769668405932, 1],
    [121.465214935973, 31.1792304387955, 1],
    [121.555755597477, 31.2476061259995, 1],
    [121.543813344366, 31.2900597632429, 1],
    [121.635650440382, 31.5453649654862, 1],
    [121.452965282717, 31.1400515859375, 1],
    [121.49872637304, 31.2528239386035, 1],
    [121.706028556561, 31.1960847058941, 1],
    [121.181707471261, 30.8329723032313, 1],
    [121.450644727822, 31.2569126811991, 1],
    [121.454650144532, 31.2236179138797, 1],
    [121.464330194877, 31.2677061674839, 1],
    [121.463551094508, 31.2461800290438, 1],
    [121.479567252937, 30.9043490529513, 1],
    [121.450669932478, 31.1798782322945, 1],
    [121.469876782248, 31.273721070047, 1],
    [121.478999434024, 31.2795290407276, 1],
    [121.71677686014, 31.5714662012807, 1],
    [121.388644811592, 31.0451776545436, 1],
    [121.472665892399, 31.2820143681501, 1],
    [121.546845754276, 30.8842458030581, 1],
    [121.528485916772, 31.1491919897198, 1],
    [121.509128688863, 31.391799400684, 1],
    [121.336286446129, 30.9694551538532, 1],
    [121.533456348955, 31.2902873183547, 1],
    [121.575195377866, 30.8818805394424, 1],
    [121.428973069665, 31.2490758081842, 1],
    [121.421012016744, 31.0242929242325, 1],
    [121.739664897619, 31.2158780073101, 1],
    [121.510869157585, 31.1505132517594, 1],
    [121.500003254136, 31.279784424511, 1],
    [121.507171258699, 31.2770354649283, 1],
    [121.414561913691, 31.1723057896537, 1],
    [121.121517363955, 31.0393932550249, 1],
    [121.783298449257, 31.557627877066, 1],
    [121.72748484148, 31.2450467461425, 1],
    [121.505296471744, 31.2728183761705, 1],
    [121.553301372027, 31.1781180034025, 1],
    [121.365430171789, 30.8138062538024, 1],
    [121.721630128978, 31.1870486414338, 1],
    [121.776288252718, 31.0498401721864, 1],
    [121.758236923868, 31.0544658639371, 1],
    [121.188585976212, 30.86629065447, 1],
    [121.465467988636, 31.1223618906381, 1],
    [121.494884436255, 31.2700104379951, 1],
    [121.247506104103, 31.3808738027498, 1],
    [121.495141804377, 31.2668828894747, 1],
    [121.488696542292, 31.2574312290438, 1],
    [121.331443225684, 31.1325951106451, 1],
    [121.335418772837, 31.4913986494108, 1],
    [121.437025300595, 31.1873939678411, 1],
    [121.461633861719, 31.193104504312, 1],
    [121.468325588293, 31.1982293113814, 1],
    [121.291087036597, 31.4750768878192, 1],
    [121.58186080475, 30.9343657196239, 1],
    [121.406240686074, 31.2819222291192, 1],
    [121.243899137989, 31.187891902589, 1],
    [121.458180575016, 31.1909826337903, 1],
    [121.443003015323, 31.2610767501236, 1],
    [121.482461323798, 31.0500012032459, 1],
    [121.448035741401, 31.2286574910561, 1],
    [121.4286673763, 31.2500346935075, 1],
    [121.465941634589, 31.2411835226494, 1],
    [121.47488214055, 31.214948326159, 1],
    [121.140893586534, 31.1513909887407, 1],
    [121.1271191522, 31.1493519236033, 1],
    [121.242035693039, 31.1869414166069, 1],
    [121.510125719945, 31.1779356880003, 1],
    [121.507055850695, 31.2199578743679, 1],
    [121.122733714531, 30.981279778389, 1],
    [121.090367587345, 31.1015769134168, 1],
    [121.504345123988, 31.2787991484811, 1],
    [121.628175338402, 31.2184193161849, 1],
    [121.502638343519, 31.2278469156163, 1],
    [121.503298598069, 31.285909876882, 1],
    [121.237590518053, 31.0232337080953, 1],
    [121.366275477274, 31.17683803613, 1],
    [121.471235469332, 31.2233013872603, 1],
    [121.389026117128, 31.17126239187, 1],
    [121.342559582997, 31.1621795877182, 1],
    [121.430530478996, 31.2421424221398, 1],
    [121.477149599301, 31.2254820907399, 1],
    [121.393680981772, 31.2590501580303, 1],
    [121.48209804905, 31.2132159800014, 1],
    [121.420493335143, 31.7681656763809, 1],
    [121.582381642284, 31.3485925969088, 1],
    [121.486098960758, 31.217478100135, 1],
    [121.358581221089, 31.1855487638508, 1],
    [121.511496006848, 31.2739677329719, 1],
    [121.403994247671, 31.2399168155794, 1],
    [121.449071397823, 31.6374379171314, 1],
    [121.426679695698, 31.2418508962029, 1],
    [121.377091165445, 31.3302020103217, 1],
    [121.58110119761, 31.3465038287535, 1],
    [121.41755997689, 31.2231337685343, 1],
    [121.536099415291, 31.2944450601459, 1],
    [121.384180412868, 31.1668200849803, 1],
    [121.54864880435, 31.2924318271243, 1],
    [121.440578637871, 31.22898581071, 1],
    [121.728364821558, 30.9045833801847, 1],
    [121.420842596325, 31.2039788073646, 1],
    [121.596981091358, 31.0539844118814, 1],
    [121.340410926047, 31.015626436798, 1],
    [121.118431955816, 31.21813667724, 1],
    [121.402083905784, 31.2663193097096, 1],
    [121.485099835725, 31.2107192821164, 1],
    [121.586235462753, 31.5698649329417, 1],
    [121.349712071128, 31.4210862417172, 1],
    [121.179309804024, 30.9848108094534, 1],
    [121.322950112697, 31.0147123531388, 1],
    [121.389868483357, 31.1492501685988, 1],
    [121.398109987259, 31.1572808257147, 1],
    [121.506890023498, 31.3139295019622, 1],
    [121.221329751034, 31.2696294876409, 1],
    [121.345510425868, 31.0660854046467, 1],
    [121.368771958117, 31.2148392302949, 1],
    [121.044138450207, 31.0102293927926, 1],
    [121.561195979984, 31.1910475233022, 1],
    [121.161017417585, 31.2393889098273, 1],
    [121.374229002395, 31.6845129694279, 1],
    [121.440467158157, 31.3250633380773, 1],
    [121.32840237799, 31.1315730248588, 1],
    [121.196337454457, 31.2107589691386, 1],
    [121.399970469597, 31.2566826607024, 1],
    [121.519492620989, 31.1821871429284, 1],
    [121.71609702253, 31.3912639216569, 1],
    [121.454571164613, 31.1274657497915, 1],
    [121.298530665544, 31.2995041924452, 1],
    [121.501285585252, 31.4129823235069, 1],
    [121.330682996019, 31.4892259473356, 1],
    [121.542613028544, 31.3402368577107, 1],
    [121.49629495916, 31.4139449169937, 1],
    [121.397906769891, 31.0652244313931, 1],
    [121.390762656662, 31.1924916644135, 1],
    [121.452702977508, 31.0478478347915, 1],
    [121.369393495699, 31.3591024174287, 1],
    [121.314397345937, 31.2268871852175, 1],
    [121.476644576435, 31.3127884455024, 1],
    [121.366948487762, 31.1223582582483, 1],
    [121.409174506056, 31.14956802707, 1],
    [121.501846648009, 31.2960255004953, 1],
    [121.308208916583, 31.3267052965769, 1],
    [121.482569300121, 31.2866841516211, 1],
];

//---------------------------------------------

var mapv = {};
(function (global, factory) {
    // console.log(global,factory)
    // typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    //     typeof define === 'function' && define.amd ? define(['exports'], factory) :
    //     (factory((global.mapv = global.mapv || {})));
    factory(mapv);
})(window, function (exports) {
    'use strict';

    var version = '2.0.13';

    /**
     * @author kyle / http://nikai.us/
     */

    var clear = function (context) {
        context && context.clearRect && context.clearRect(0, 0, context.canvas.width, context.canvas.height);
        //context.canvas.width = context.canvas.width;
        //context.canvas.height = context.canvas.height;
    };

    /**
     * @author kyle / http://nikai.us/
     */

    var resolutionScale$1 = function (context) {
        var devicePixelRatio = window.devicePixelRatio;
        context.canvas.width = context.canvas.width * devicePixelRatio;
        context.canvas.height = context.canvas.height * devicePixelRatio;
        context.canvas.style.width = context.canvas.width / devicePixelRatio + 'px';
        context.canvas.style.height = context.canvas.height / devicePixelRatio + 'px';
        context.scale(devicePixelRatio, devicePixelRatio);
    };

    function Event() {
        this._subscribers = {}; // event subscribers
    }

    /**
     * Subscribe to an event, add an event listener
     * @param {String} event        Event name. Available events: 'put', 'update',
     *                              'remove'
     * @param {function} callback   Callback method. Called with three parameters:
     *                                  {String} event
     *                                  {Object | null} params
     *                                  {String | Number} senderId
     */
    Event.prototype.on = function (event, callback) {
        var subscribers = this._subscribers[event];
        if (!subscribers) {
            subscribers = [];
            this._subscribers[event] = subscribers;
        }

        subscribers.push({
            callback: callback,
        });
    };

    /**
     * Unsubscribe from an event, remove an event listener
     * @param {String} event
     * @param {function} callback
     */
    Event.prototype.off = function (event, callback) {
        var subscribers = this._subscribers[event];
        if (subscribers) {
            //this._subscribers[event] = subscribers.filter(listener => listener.callback != callback);
            for (var i = 0; i < subscribers.length; i++) {
                if (subscribers[i].callback == callback) {
                    subscribers.splice(i, 1);
                    i--;
                }
            }
        }
    };

    /**
     * Trigger an event
     * @param {String} event
     * @param {Object | null} params
     * @param {String} [senderId]       Optional id of the sender.
     * @private
     */
    Event.prototype._trigger = function (event, params, senderId) {
        if (event == '*') {
            throw new Error('Cannot trigger event *');
        }

        var subscribers = [];
        if (event in this._subscribers) {
            subscribers = subscribers.concat(this._subscribers[event]);
        }
        if ('*' in this._subscribers) {
            subscribers = subscribers.concat(this._subscribers['*']);
        }

        for (var i = 0, len = subscribers.length; i < len; i++) {
            var subscriber = subscribers[i];
            if (subscriber.callback) {
                subscriber.callback(event, params, senderId || null);
            }
        }
    };

    var classCallCheck = function (instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError('Cannot call a class as a function');
        }
    };

    var createClass = (function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ('value' in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    })();

    var get = function get(object, property, receiver) {
        if (object === null) object = Function.prototype;
        var desc = Object.getOwnPropertyDescriptor(object, property);

        if (desc === undefined) {
            var parent = Object.getPrototypeOf(object);

            if (parent === null) {
                return undefined;
            } else {
                return get(parent, property, receiver);
            }
        } else if ('value' in desc) {
            return desc.value;
        } else {
            var getter = desc.get;

            if (getter === undefined) {
                return undefined;
            }

            return getter.call(receiver);
        }
    };

    var inherits = function (subClass, superClass) {
        if (typeof superClass !== 'function' && superClass !== null) {
            throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
        }

        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true,
            },
        });
        if (superClass)
            Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : (subClass.__proto__ = superClass);
    };

    var possibleConstructorReturn = function (self, call) {
        if (!self) {
            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }

        return call && (typeof call === 'object' || typeof call === 'function') ? call : self;
    };

    /**
     * @author kyle / http://nikai.us/
     */

    /**
     * DataSet
     *
     * A data set can:
     * - add/remove/update data
     * - gives triggers upon changes in the data
     * - can  import/export data in various data formats
     * @param {Array} [data]    Optional array with initial data
     * the field geometry is like geojson, it can be:
     * {
     *     "type": "Point",
     *     "coordinates": [125.6, 10.1]
     * }
     * {
     *     "type": "LineString",
     *     "coordinates": [
     *         [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
     *     ]
     * }
     * {
     *     "type": "Polygon",
     *     "coordinates": [
     *         [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
     *           [100.0, 1.0], [100.0, 0.0] ]
     *     ]
     * }
     * @param {Object} [options]   Available options:
     *
     */
    function DataSet(data, options) {
        this._options = options || {};
        this._data = []; // map with data indexed by id

        // add initial data when provided
        if (data) {
            this.add(data);
        }
    }

    DataSet.prototype = new Event();

    /**
     * Add data.
     */
    DataSet.prototype.add = function (data, senderId) {
        if (Array.isArray(data)) {
            // Array
            for (var i = 0, len = data.length; i < len; i++) {
                if (data[i].time && data[i].time.length == 14 && data[i].time.substr(0, 2) == '20') {
                    var time = data[i].time;
                    data[i].time = new Date(
                        time.substr(0, 4) +
                            '-' +
                            time.substr(4, 2) +
                            '-' +
                            time.substr(6, 2) +
                            ' ' +
                            time.substr(8, 2) +
                            ':' +
                            time.substr(10, 2) +
                            ':' +
                            time.substr(12, 2)
                    ).getTime();
                }
                this._data.push(data[i]);
            }
        } else if (data instanceof Object) {
            // Single item
            this._data.push(data);
        } else {
            throw new Error('Unknown dataType');
        }
    };

    /**
     * get data.
     */
    DataSet.prototype.get = function (args) {
        args = args || {};

        //console.time('copy data time')
        var start = new Date();
        // TODO: 不修改原始数据,在数据上挂载新的名称,每次修改数据直接修改新名称下的数据,可以省去deepCopy
        // var data = deepCopy(this._data);
        var data = this._data;

        // console.timeEnd('copy data time')

        // console.time('transferCoordinate time')

        var start = new Date();

        if (args.filter) {
            var newData = [];
            for (var i = 0; i < data.length; i++) {
                if (args.filter(data[i])) {
                    newData.push(data[i]);
                }
            }
            data = newData;
        }

        if (args.transferCoordinate) {
            data = this.transferCoordinate(data, args.transferCoordinate, args.fromColumn, args.toColumn);
        }

        // console.timeEnd('transferCoordinate time')

        return data;
    };

    /**
     * set data.
     */
    DataSet.prototype.set = function (data) {
        this._set(data);
        this._trigger('change');
    };

    /**
     * set data.
     */
    DataSet.prototype._set = function (data) {
        this.clear();
        this.add(data);
    };

    /**
     * clear data.
     */
    DataSet.prototype.clear = function (args) {
        this._data = []; // map with data indexed by id
    };

    /**
     * remove data.
     */
    DataSet.prototype.remove = function (args) {};

    /**
     * update data.
     */
    DataSet.prototype.update = function (args) {};

    /**
     * transfer coordinate.
     */
    DataSet.prototype.transferCoordinate = function (data, transferFn, fromColumn, toColumnName) {
        toColumnName = toColumnName || '_coordinates';
        fromColumn = fromColumn || 'coordinates';

        for (var i = 0; i < data.length; i++) {
            var geometry = data[i].geometry;
            var coordinates = geometry[fromColumn];
            switch (geometry.type) {
                case 'Point':
                    geometry[toColumnName] = transferFn(coordinates);
                    break;
                case 'LineString':
                    var newCoordinates = [];
                    for (var j = 0; j < coordinates.length; j++) {
                        newCoordinates.push(transferFn(coordinates[j]));
                    }
                    geometry[toColumnName] = newCoordinates;
                    break;
                case 'Polygon':
                    var newCoordinates = getPolygon(coordinates);
                    geometry[toColumnName] = newCoordinates;
                    break;
                case 'MultiPolygon':
                    var newCoordinates = [];
                    for (var c = 0; c < coordinates.length; c++) {
                        var polygon = coordinates[c];
                        var polygon = getPolygon(polygon);
                        newCoordinates.push(polygon);
                    }

                    geometry[toColumnName] = newCoordinates;
                    break;
            }
        }

        function getPolygon(coordinates) {
            var newCoordinates = [];
            for (var c = 0; c < coordinates.length; c++) {
                var coordinate = coordinates[c];
                var newcoordinate = [];
                for (var j = 0; j < coordinate.length; j++) {
                    newcoordinate.push(transferFn(coordinate[j]));
                }
                newCoordinates.push(newcoordinate);
            }
            return newCoordinates;
        }

        return data;
    };

    DataSet.prototype.initGeometry = function (transferFn) {
        if (transferFn) {
            this._data.forEach(function (item) {
                item.geometry = transferFn(item);
            });
        } else {
            this._data.forEach(function (item) {
                if (!item.geometry && item.lng && item.lat) {
                    item.geometry = {
                        type: 'Point',
                        coordinates: [item.lng, item.lat],
                    };
                }
            });
        }
    };

    /**
     * 获取当前列的最大值
     */
    DataSet.prototype.getMax = function (columnName) {
        var data = this._data;

        if (!data || data.length <= 0) {
            return;
        }

        var max = parseFloat(data[0][columnName]);

        for (var i = 1; i < data.length; i++) {
            var value = parseFloat(data[i][columnName]);
            if (value > max) {
                max = value;
            }
        }

        return max;
    };

    /**
     * 获取当前列的总和
     */
    DataSet.prototype.getSum = function (columnName) {
        var data = this._data;

        if (!data || data.length <= 0) {
            return;
        }

        var sum = 0;

        for (var i = 0; i < data.length; i++) {
            if (data[i][columnName]) {
                sum += parseFloat(data[i][columnName]);
            }
        }

        return sum;
    };

    /**
     * 获取当前列的最小值
     */
    DataSet.prototype.getMin = function (columnName) {
        var data = this._data;

        if (!data || data.length <= 0) {
            return;
        }

        var min = parseFloat(data[0][columnName]);

        for (var i = 1; i < data.length; i++) {
            var value = parseFloat(data[i][columnName]);
            if (value < min) {
                min = value;
            }
        }

        return min;
    };

    /**
     * @author kyle / http://nikai.us/
     */

    var pathSimple = {
        drawDataSet: function drawDataSet(context, dataSet, options) {
            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

            for (var i = 0, len = data.length; i < len; i++) {
                var item = data[i];
                this.draw(context, item, options);
            }
        },
        draw: function draw(context, data, options) {
            var type = data.geometry.type;
            var coordinates = data.geometry._coordinates || data.geometry.coordinates;
            var symbol = options.symbol || 'circle';
            switch (type) {
                case 'Point':
                    var size = data._size || data.size || options._size || options.size || 5;
                    if (options.symbol === 'rect') {
                        context.rect(coordinates[0] - size / 2, coordinates[1] - size / 2, size, size);
                    } else {
                        if (options.bigData === 'Point') {
                            context.moveTo(coordinates[0], coordinates[1]);
                        }
                        context.arc(coordinates[0], coordinates[1], size, 0, Math.PI * 2);
                    }
                    break;
                case 'LineString':
                    for (var j = 0; j < coordinates.length; j++) {
                        var x = coordinates[j][0];
                        var y = coordinates[j][1];
                        if (j == 0) {
                            context.moveTo(x, y);
                        } else {
                            context.lineTo(x, y);
                        }
                    }
                    break;
                case 'Polygon':
                    this.drawPolygon(context, coordinates);
                    break;
                case 'MultiPolygon':
                    for (var i = 0; i < coordinates.length; i++) {
                        var polygon = coordinates[i];
                        this.drawPolygon(context, polygon);
                    }
                    context.closePath();
                    break;
                default:
                    console.log('type' + type + 'is not support now!');
                    break;
            }
        },

        drawPolygon: function drawPolygon(context, coordinates) {
            for (var i = 0; i < coordinates.length; i++) {
                var coordinate = coordinates[i];

                context.moveTo(coordinate[0][0], coordinate[0][1]);
                for (var j = 1; j < coordinate.length; j++) {
                    context.lineTo(coordinate[j][0], coordinate[j][1]);
                }
                context.lineTo(coordinate[0][0], coordinate[0][1]);
            }
        },
    };

    /**
     * @author kyle / http://nikai.us/
     */

    var drawSimple = {
        draw: function draw(context, dataSet, options) {
            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

            // console.log('xxxx',options)
            context.save();

            for (var key in options) {
                context[key] = options[key];
            }

            // console.log(data);
            if (options.bigData) {
                context.save();
                context.beginPath();

                for (var i = 0, len = data.length; i < len; i++) {
                    var item = data[i];

                    pathSimple.draw(context, item, options);
                }

                var type = options.bigData;

                if (type == 'Point' || type == 'Polygon' || type == 'MultiPolygon') {
                    context.fill();

                    if ((item.strokeStyle || options.strokeStyle) && options.lineWidth) {
                        context.stroke();
                    }
                } else if (type == 'LineString') {
                    context.stroke();
                }

                context.restore();
            } else {
                for (var i = 0, len = data.length; i < len; i++) {
                    var item = data[i];

                    context.save();

                    if (item.fillStyle) {
                        context.fillStyle = item.fillStyle;
                    }

                    if (item.strokeStyle) {
                        context.strokeStyle = item.strokeStyle;
                    }

                    var type = item.geometry.type;

                    context.beginPath();

                    pathSimple.draw(context, item, options);

                    if (type == 'Point' || type == 'Polygon' || type == 'MultiPolygon') {
                        context.fill();

                        if ((item.strokeStyle || options.strokeStyle) && options.lineWidth) {
                            context.stroke();
                        }
                    } else if (type == 'LineString') {
                        context.stroke();
                    }

                    context.restore();
                }
            }

            context.restore();
        },
    };

    function Canvas(width, height) {
        var canvas;

        if (typeof document === 'undefined') {
            var Canvas = require('canvas');
            canvas = new Canvas(width, height);
        } else {
            var canvas = document.createElement('canvas');

            if (width) {
                canvas.width = width;
            }

            if (height) {
                canvas.height = height;
            }
        }

        return canvas;
    }

    /**
     * @author kyle / http://nikai.us/
     */

    /**
     * Category
     * @param {Object} [options]   Available options:
     *                             {Object} gradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"}
     */
    function Intensity(options) {
        options = options || {};
        this.gradient = options.gradient || {
            0.25: 'rgba(0, 0, 255, 1)',
            0.55: 'rgba(0, 255, 0, 1)',
            0.85: 'rgba(255, 255, 0, 1)',
            1.0: 'rgba(255, 0, 0, 1)',
        };
        this.maxSize = options.maxSize || 35;
        this.minSize = options.minSize || 0;
        this.max = options.max || 100;
        this.min = options.min || 0;
        this.initPalette();
    }

    Intensity.prototype.setMax = function (value) {
        this.max = value || 100;
    };

    Intensity.prototype.setMin = function (value) {
        this.min = value || 0;
    };

    Intensity.prototype.setMaxSize = function (maxSize) {
        this.maxSize = maxSize || 35;
    };

    Intensity.prototype.setMinSize = function (minSize) {
        this.minSize = minSize || 0;
    };

    Intensity.prototype.initPalette = function () {
        var gradient = this.gradient;

        var canvas = new Canvas(256, 1);

        var paletteCtx = (this.paletteCtx = canvas.getContext('2d'));

        var lineGradient = paletteCtx.createLinearGradient(0, 0, 256, 1);

        for (var key in gradient) {
            lineGradient.addColorStop(parseFloat(key), gradient[key]);
        }

        paletteCtx.fillStyle = lineGradient;
        paletteCtx.fillRect(0, 0, 256, 1);
    };

    Intensity.prototype.getColor = function (value) {
        var imageData = this.getImageData(value);

        return 'rgba(' + imageData[0] + ', ' + imageData[1] + ', ' + imageData[2] + ', ' + imageData[3] / 256 + ')';
    };

    Intensity.prototype.getImageData = function (value) {
        var imageData = this.paletteCtx.getImageData(0, 0, 256, 1).data;

        if (value === undefined) {
            return imageData;
        }

        var max = this.max;
        var min = this.min;

        if (value > max) {
            value = max;
        }

        if (value < min) {
            value = min;
        }

        var index = Math.floor(((value - min) / (max - min)) * (256 - 1)) * 4;

        return [imageData[index], imageData[index + 1], imageData[index + 2], imageData[index + 3]];
    };

    /**
     * @param Number value
     * @param Number max of value
     * @param Number max of size
     * @param Object other options
     */
    Intensity.prototype.getSize = function (value) {
        var size = 0;
        var max = this.max;
        var min = this.min;
        var maxSize = this.maxSize;
        var minSize = this.minSize;

        if (value > max) {
            value = max;
        }

        if (value < min) {
            value = min;
        }

        size = minSize + ((value - min) / (max - min)) * (maxSize - minSize);

        return size;
    };

    Intensity.prototype.getLegend = function (options) {
        var gradient = this.gradient;

        var width = options.width || 20;
        var height = options.height || 180;

        var canvas = new Canvas(width, height);

        var paletteCtx = canvas.getContext('2d');

        var lineGradient = paletteCtx.createLinearGradient(0, height, 0, 0);

        for (var key in gradient) {
            lineGradient.addColorStop(parseFloat(key), gradient[key]);
        }

        paletteCtx.fillStyle = lineGradient;
        paletteCtx.fillRect(0, 0, width, height);

        return canvas;
    };

    var global$1 = typeof window === 'undefined' ? {} : window;

    var devicePixelRatio = global$1.devicePixelRatio;

    /**
     * @author kyle / http://nikai.us/
     */

    function createCircle(size) {
        var shadowBlur = size / 2;
        var r2 = size + shadowBlur;
        var offsetDistance = 10000;

        var circle = new Canvas(r2 * 2, r2 * 2);
        var context = circle.getContext('2d');

        context.shadowBlur = shadowBlur;
        context.shadowColor = 'black';
        context.shadowOffsetX = context.shadowOffsetY = offsetDistance;

        context.beginPath();
        context.arc(r2 - offsetDistance, r2 - offsetDistance, size, 0, Math.PI * 2, true);
        context.closePath();
        context.fill();
        return circle;
    }

    function colorize(pixels, gradient, options) {
        var maxOpacity = options.maxOpacity || 0.8;
        for (var i = 3, len = pixels.length, j; i < len; i += 4) {
            j = pixels[i] * 4; // get gradient color from opacity value

            if (pixels[i] / 256 > maxOpacity) {
                pixels[i] = 256 * maxOpacity;
            }

            pixels[i - 3] = gradient[j];
            pixels[i - 2] = gradient[j + 1];
            pixels[i - 1] = gradient[j + 2];
        }
    }

    function drawGray(context, dataSet, options) {
        var max = options.max || 100;
        var min = options.min || 0;
        // console.log(max)
        var size = options._size;
        if (size == undefined) {
            size = options.size;
            if (size == undefined) {
                size = 13;
            }
        }

        var intensity = new Intensity({
            gradient: options.gradient,
            max: max,
            min: min,
        });

        var circle = createCircle(size);
        var circleHalfWidth = circle.width / 2;
        var circleHalfHeight = circle.height / 2;

        var data = dataSet;

        var dataOrderByAlpha = {};

        data.forEach(function (item, index) {
            var count = item.count === undefined ? 1 : item.count;
            var alpha = Math.min(1, count / max).toFixed(2);
            dataOrderByAlpha[alpha] = dataOrderByAlpha[alpha] || [];
            dataOrderByAlpha[alpha].push(item);
        });

        for (var i in dataOrderByAlpha) {
            if (isNaN(i)) continue;
            var _data = dataOrderByAlpha[i];
            context.beginPath();
            if (!options.withoutAlpha) {
                context.globalAlpha = i;
            }
            context.strokeStyle = intensity.getColor(i * max);
            _data.forEach(function (item, index) {
                if (!item.geometry) {
                    return;
                }

                var coordinates = item.geometry._coordinates || item.geometry.coordinates;
                var type = item.geometry.type;
                if (type === 'Point') {
                    var count = item.count === undefined ? 1 : item.count;
                    context.globalAlpha = count / max;
                    context.drawImage(circle, coordinates[0] - circleHalfWidth, coordinates[1] - circleHalfHeight);
                } else if (type === 'LineString') {
                    var count = item.count === undefined ? 1 : item.count;
                    context.globalAlpha = count / max;
                    context.beginPath();
                    pathSimple.draw(context, item, options);
                    context.stroke();
                } else if (type === 'Polygon') {
                }
            });
        }
    }

    function draw(context, dataSet, options) {
        var strength = options.strength || 0.3;
        context.strokeStyle = 'rgba(0,0,0,' + strength + ')';
        var shadowCanvas = new Canvas(context.canvas.width, context.canvas.height);
        var shadowContext = shadowCanvas.getContext('2d');
        shadowContext.scale(devicePixelRatio, devicePixelRatio);

        options = options || {};

        var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

        context.save();

        var intensity = new Intensity({
            gradient: options.gradient,
        });

        //console.time('drawGray')
        drawGray(shadowContext, data, options);

        //console.timeEnd('drawGray');
        // return false;
        if (!options.absolute) {
            //console.time('changeColor');
            var colored = shadowContext.getImageData(0, 0, context.canvas.width, context.canvas.height);
            colorize(colored.data, intensity.getImageData(), options);
            //console.timeEnd('changeColor');
            context.putImageData(colored, 0, 0);

            context.restore();
        }

        intensity = null;
        shadowCanvas = null;
    }

    var drawHeatmap = {
        draw: draw,
    };

    /**
     * @author kyle / http://nikai.us/
     */

    var drawGrid = {
        draw: function draw(context, dataSet, options) {
            context.save();

            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

            var grids = {};
            var gridIndexData = {};
            var size = options._size || options.size || 50;

            var offset = options.offset || {
                x: 0,
                y: 0,
            };

            for (var i = 0; i < data.length; i++) {
                var coordinates = data[i].geometry._coordinates || data[i].geometry.coordinates;
                var gridKey =
                    Math.floor((coordinates[0] - offset.x) / size) +
                    ',' +
                    Math.floor((coordinates[1] - offset.y) / size);

                if (!grids[gridKey]) {
                    grids[gridKey] = 0;
                    gridIndexData[gridKey] = [];
                }
                var count = ~~(data[i].count || 1);
                grids[gridKey] += count;
                gridIndexData[gridKey].push(data[i]);
            }

            for (var gridKey in grids) {
                var total = grids[gridKey];
                gridIndexData[gridKey].forEach((i) => {
                    i.total = total;
                    i.average = parseInt(total / gridIndexData[gridKey].length);
                });
            }

            var intensity = new Intensity({
                max: options.max || 100,
                gradient: options.gradient,
            });

            for (var gridKey in grids) {
                gridKey = gridKey.split(',');

                context.beginPath();
                context.rect(gridKey[0] * size + 0.5 + offset.x, gridKey[1] * size + 0.5 + offset.y, size, size);
                var text = grids[gridKey];
                if (options.label.average) {
                    text = parseInt(grids[gridKey] / gridIndexData[gridKey].length);
                }

                context.fillStyle = intensity.getColor(text);
                context.fill();
                if (options.strokeStyle && options.lineWidth) {
                    context.stroke();
                }
            }

            if (options.label && options.label.show !== false) {
                context.fillStyle = options.label.fillStyle || 'white';

                if (options.label.font) {
                    context.font = options.label.font;
                }

                if (options.label.shadowColor) {
                    context.shadowColor = options.label.shadowColor;
                }

                if (options.label.shadowBlur) {
                    context.shadowBlur = options.label.shadowBlur;
                }

                for (var gridKey in grids) {
                    gridKey = gridKey.split(',');
                    var text = grids[gridKey];
                    if (options.label.average) {
                        text = parseInt(text / gridIndexData[gridKey].length);
                    }

                    var textWidth = context.measureText(text).width;
                    context.fillText(
                        text,
                        gridKey[0] * size + 0.5 + offset.x + size / 2 - textWidth / 2,
                        gridKey[1] * size + 0.5 + offset.y + size / 2 + 5
                    );
                }
            }

            context.restore();
        },
    };

    /**
     * @author kyle / http://nikai.us/
     */

    function hex_corner(center, size, i) {
        var angle_deg = 60 * i + 30;
        var angle_rad = (Math.PI / 180) * angle_deg;
        return [center.x + size * Math.cos(angle_rad), center.y + size * Math.sin(angle_rad)];
    }

    var drawHoneycomb = {
        draw: function draw(context, dataSet, options) {
            context.save();

            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

            for (var key in options) {
                context[key] = options[key];
            }

            var grids = {};

            var offset = options.offset || {
                x: 10,
                y: 10,
            };

            //
            var r = options._size || options.size || 40;
            r = r / 2 / Math.sin(Math.PI / 3);
            var dx = r * 2 * Math.sin(Math.PI / 3);
            var dy = r * 1.5;

            var binsById = {};

            for (var i = 0; i < data.length; i++) {
                var coordinates = data[i].geometry._coordinates || data[i].geometry.coordinates;
                var py = (coordinates[1] - offset.y) / dy,
                    pj = Math.round(py),
                    px = (coordinates[0] - offset.x) / dx - (pj & 1 ? 0.5 : 0),
                    pi = Math.round(px),
                    py1 = py - pj;

                if (Math.abs(py1) * 3 > 1) {
                    var px1 = px - pi,
                        pi2 = pi + (px < pi ? -1 : 1) / 2,
                        pj2 = pj + (py < pj ? -1 : 1),
                        px2 = px - pi2,
                        py2 = py - pj2;
                    if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) (pi = pi2 + (pj & 1 ? 1 : -1) / 2), (pj = pj2);
                }

                var id = pi + '-' + pj,
                    bin = binsById[id];
                if (bin) {
                    bin.push(data[i]);
                } else {
                    bin = binsById[id] = [data[i]];
                    bin.i = pi;
                    bin.j = pj;
                    bin.x = (pi + (pj & 1 ? 1 / 2 : 0)) * dx;
                    bin.y = pj * dy;
                }
            }

            var intensity = new Intensity({
                max: options.max || 100,
                maxSize: r,
                gradient: options.gradient,
            });

            for (var key in binsById) {
                var item = binsById[key];

                context.beginPath();

                for (var j = 0; j < 6; j++) {
                    var radius = r;

                    var result = hex_corner(
                        {
                            x: item.x + offset.x,
                            y: item.y + offset.y,
                        },
                        radius,
                        j
                    );
                    context.lineTo(result[0], result[1]);
                }
                context.closePath();

                var count = 0;
                for (var i = 0; i < item.length; i++) {
                    count += item[i].count || 1;
                }
                item.count = count;

                context.fillStyle = intensity.getColor(count);
                context.fill();
                if (options.strokeStyle && options.lineWidth) {
                    context.stroke();
                }
            }

            if (options.label && options.label.show !== false) {
                context.fillStyle = options.label.fillStyle || 'white';

                if (options.label.font) {
                    context.font = options.label.font;
                }

                if (options.label.shadowColor) {
                    context.shadowColor = options.label.shadowColor;
                }

                if (options.label.shadowBlur) {
                    context.shadowBlur = options.label.shadowBlur;
                }

                for (var key in binsById) {
                    var item = binsById[key];
                    var text = item.count;
                    if (text < 0) {
                        text = text.toFixed(2);
                    } else {
                        text = ~~text;
                    }
                    var textWidth = context.measureText(text).width;
                    context.fillText(text, item.x + offset.x - textWidth / 2, item.y + offset.y + 5);
                }
            }

            context.restore();
        },
    };

    function createShader(gl, src, type) {
        var shader = gl.createShader(type);
        gl.shaderSource(shader, src);
        gl.compileShader(shader);
        return shader;
    }

    function initShaders(gl, vs_source, fs_source) {
        var vertexShader = createShader(gl, vs_source, gl.VERTEX_SHADER);
        var fragmentShader = createShader(gl, fs_source, gl.FRAGMENT_SHADER);

        var glProgram = gl.createProgram();

        gl.attachShader(glProgram, vertexShader);
        gl.attachShader(glProgram, fragmentShader);
        gl.linkProgram(glProgram);

        gl.useProgram(glProgram);

        return glProgram;
    }

    function getColorData(color) {
        var tmpCanvas = document.createElement('canvas');
        var tmpCtx = tmpCanvas.getContext('2d');
        tmpCanvas.width = 1;
        tmpCanvas.height = 1;
        tmpCtx.fillStyle = color;
        tmpCtx.fillRect(0, 0, 1, 1);
        return tmpCtx.getImageData(0, 0, 1, 1).data;
    }

    var vs_s = [
        'attribute vec4 a_Position;',
        'void main() {',
        'gl_Position = a_Position;',
        'gl_PointSize = 30.0;',
        '}',
    ].join('');

    var fs_s = [
        'precision mediump float;',
        'uniform vec4 u_FragColor;',
        'void main() {',
        'gl_FragColor = u_FragColor;',
        '}',
    ].join('');

    function draw$1(gl, data, options) {
        if (!data) {
            return;
        }

        var program = initShaders(gl, vs_s, fs_s);

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

        //gl.clearColor(0.0, 0.0, 1.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        var halfCanvasWidth = gl.canvas.width / 2;
        var halfCanvasHeight = gl.canvas.height / 2;

        // Create a buffer object
        var vertexBuffer = gl.createBuffer();
        // Bind the buffer object to target
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

        var a_Position = gl.getAttribLocation(program, 'a_Position');
        // Assign the buffer object to a_Position variable
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

        // Enable the assignment to a_Position variable
        gl.enableVertexAttribArray(a_Position);

        var uFragColor = gl.getUniformLocation(program, 'u_FragColor');

        var colored = getColorData(options.strokeStyle || 'red');

        gl.uniform4f(uFragColor, colored[0] / 255, colored[1] / 255, colored[2] / 255, colored[3] / 255);

        gl.lineWidth(options.lineWidth || 1);

        for (var i = 0, len = data.length; i < len; i++) {
            var _geometry = data[i].geometry._coordinates;

            var verticesData = [];

            for (var j = 0; j < _geometry.length; j++) {
                var item = _geometry[j];

                var x = (item[0] - halfCanvasWidth) / halfCanvasWidth;
                var y = (halfCanvasHeight - item[1]) / halfCanvasHeight;
                verticesData.push(x, y);
            }

            var vertices = new Float32Array(verticesData);
            // Write date into the buffer object
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
            gl.drawArrays(gl.LINE_STRIP, 0, _geometry.length);
        }
    }

    var line = {
        draw: draw$1,
    };

    var vs_s$1 = [
        'attribute vec4 a_Position;',
        'attribute float a_PointSize;',
        'void main() {',
        'gl_Position = a_Position;',
        'gl_PointSize = a_PointSize;',
        '}',
    ].join('');

    var fs_s$1 = [
        'precision mediump float;',
        'uniform vec4 u_FragColor;',
        'void main() {',
        'gl_FragColor = u_FragColor;',
        '}',
    ].join('');

    function draw$2(gl, data, options) {
        if (!data) {
            return;
        }

        var program = initShaders(gl, vs_s$1, fs_s$1);

        var a_Position = gl.getAttribLocation(program, 'a_Position');

        var a_PointSize = gl.getAttribLocation(program, 'a_PointSize');

        var uFragColor = gl.getUniformLocation(program, 'u_FragColor');

        //gl.clearColor(0.0, 0.0, 1.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        var halfCanvasWidth = gl.canvas.width / 2;
        var halfCanvasHeight = gl.canvas.height / 2;

        var verticesData = [];
        var count = 0;
        for (var i = 0; i < data.length; i++) {
            var item = data[i].geometry._coordinates;

            var x = (item[0] - halfCanvasWidth) / halfCanvasWidth;
            var y = (halfCanvasHeight - item[1]) / halfCanvasHeight;

            if (x < -1 || x > 1 || y < -1 || y > 1) {
                continue;
            }
            verticesData.push(x, y);
            count++;
        }

        var vertices = new Float32Array(verticesData);
        var n = count; // The number of vertices

        // Create a buffer object
        var vertexBuffer = gl.createBuffer();

        // Bind the buffer object to target
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // Write date into the buffer object
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        // Assign the buffer object to a_Position variable
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

        // Enable the assignment to a_Position variable
        gl.enableVertexAttribArray(a_Position);

        gl.vertexAttrib1f(a_PointSize, options._size);

        var colored = getColorData(options.fillStyle || 'red');

        gl.uniform4f(uFragColor, colored[0] / 255, colored[1] / 255, colored[2] / 255, colored[3] / 255);
        gl.drawArrays(gl.POINTS, 0, n);
    }

    var point = {
        draw: draw$2,
    };

    function earcut(data, holeIndices, dim) {
        dim = dim || 2;

        var hasHoles = holeIndices && holeIndices.length,
            outerLen = hasHoles ? holeIndices[0] * dim : data.length,
            outerNode = linkedList(data, 0, outerLen, dim, true),
            triangles = [];

        if (!outerNode) return triangles;

        var minX, minY, maxX, maxY, x, y, size;

        if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);

        // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
        if (data.length > 80 * dim) {
            minX = maxX = data[0];
            minY = maxY = data[1];

            for (var i = dim; i < outerLen; i += dim) {
                x = data[i];
                y = data[i + 1];
                if (x < minX) minX = x;
                if (y < minY) minY = y;
                if (x > maxX) maxX = x;
                if (y > maxY) maxY = y;
            }

            // minX, minY and size are later used to transform coords into integers for z-order calculation
            size = Math.max(maxX - minX, maxY - minY);
        }

        earcutLinked(outerNode, triangles, dim, minX, minY, size);

        return triangles;
    }

    // create a circular doubly linked list from polygon points in the specified winding order
    function linkedList(data, start, end, dim, clockwise) {
        var i, last;

        if (clockwise === signedArea(data, start, end, dim) > 0) {
            for (i = start; i < end; i += dim) {
                last = insertNode(i, data[i], data[i + 1], last);
            }
        } else {
            for (i = end - dim; i >= start; i -= dim) {
                last = insertNode(i, data[i], data[i + 1], last);
            }
        }

        if (last && equals(last, last.next)) {
            removeNode(last);
            last = last.next;
        }

        return last;
    }

    // eliminate colinear or duplicate points
    function filterPoints(start, end) {
        if (!start) return start;
        if (!end) end = start;

        var p = start,
            again;
        do {
            again = false;

            if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
                removeNode(p);
                p = end = p.prev;
                if (p === p.next) return null;
                again = true;
            } else {
                p = p.next;
            }
        } while (again || p !== end);

        return end;
    }

    // main ear slicing loop which triangulates a polygon (given as a linked list)
    function earcutLinked(ear, triangles, dim, minX, minY, size, pass) {
        if (!ear) return;

        // interlink polygon nodes in z-order
        if (!pass && size) indexCurve(ear, minX, minY, size);

        var stop = ear,
            prev,
            next;

        // iterate through ears, slicing them one by one
        while (ear.prev !== ear.next) {
            prev = ear.prev;
            next = ear.next;

            if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) {
                // cut off the triangle
                triangles.push(prev.i / dim);
                triangles.push(ear.i / dim);
                triangles.push(next.i / dim);

                removeNode(ear);

                // skipping the next vertice leads to less sliver triangles
                ear = next.next;
                stop = next.next;

                continue;
            }

            ear = next;

            // if we looped through the whole remaining polygon and can't find any more ears
            if (ear === stop) {
                // try filtering points and slicing again
                if (!pass) {
                    earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1);

                    // if this didn't work, try curing all small self-intersections locally
                } else if (pass === 1) {
                    ear = cureLocalIntersections(ear, triangles, dim);
                    earcutLinked(ear, triangles, dim, minX, minY, size, 2);

                    // as a last resort, try splitting the remaining polygon into two
                } else if (pass === 2) {
                    splitEarcut(ear, triangles, dim, minX, minY, size);
                }

                break;
            }
        }
    }

    // check whether a polygon node forms a valid ear with adjacent nodes
    function isEar(ear) {
        var a = ear.prev,
            b = ear,
            c = ear.next;

        if (area(a, b, c) >= 0) return false; // reflex, can't be an ear

        // now make sure we don't have other points inside the potential ear
        var p = ear.next.next;

        while (p !== ear.prev) {
            if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
            p = p.next;
        }

        return true;
    }

    function isEarHashed(ear, minX, minY, size) {
        var a = ear.prev,
            b = ear,
            c = ear.next;

        if (area(a, b, c) >= 0) return false; // reflex, can't be an ear

        // triangle bbox; min & max are calculated like this for speed
        var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : b.x < c.x ? b.x : c.x,
            minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : b.y < c.y ? b.y : c.y,
            maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : b.x > c.x ? b.x : c.x,
            maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : b.y > c.y ? b.y : c.y;

        // z-order range for the current triangle bbox;
        var minZ = zOrder(minTX, minTY, minX, minY, size),
            maxZ = zOrder(maxTX, maxTY, minX, minY, size);

        // first look for points inside the triangle in increasing z-order
        var p = ear.nextZ;

        while (p && p.z <= maxZ) {
            if (
                p !== ear.prev &&
                p !== ear.next &&
                pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
                area(p.prev, p, p.next) >= 0
            )
                return false;
            p = p.nextZ;
        }

        // then look for points in decreasing z-order
        p = ear.prevZ;

        while (p && p.z >= minZ) {
            if (
                p !== ear.prev &&
                p !== ear.next &&
                pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
                area(p.prev, p, p.next) >= 0
            )
                return false;
            p = p.prevZ;
        }

        return true;
    }

    // go through all polygon nodes and cure small local self-intersections
    function cureLocalIntersections(start, triangles, dim) {
        var p = start;
        do {
            var a = p.prev,
                b = p.next.next;

            if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
                triangles.push(a.i / dim);
                triangles.push(p.i / dim);
                triangles.push(b.i / dim);

                // remove two nodes involved
                removeNode(p);
                removeNode(p.next);

                p = start = b;
            }
            p = p.next;
        } while (p !== start);

        return p;
    }

    // try splitting polygon into two and triangulate them independently
    function splitEarcut(start, triangles, dim, minX, minY, size) {
        // look for a valid diagonal that divides the polygon into two
        var a = start;
        do {
            var b = a.next.next;
            while (b !== a.prev) {
                if (a.i !== b.i && isValidDiagonal(a, b)) {
                    // split the polygon in two by the diagonal
                    var c = splitPolygon(a, b);

                    // filter colinear points around the cuts
                    a = filterPoints(a, a.next);
                    c = filterPoints(c, c.next);

                    // run earcut on each half
                    earcutLinked(a, triangles, dim, minX, minY, size);
                    earcutLinked(c, triangles, dim, minX, minY, size);
                    return;
                }
                b = b.next;
            }
            a = a.next;
        } while (a !== start);
    }

    // link every hole into the outer loop, producing a single-ring polygon without holes
    function eliminateHoles(data, holeIndices, outerNode, dim) {
        var queue = [],
            i,
            len,
            start,
            end,
            list;

        for (i = 0, len = holeIndices.length; i < len; i++) {
            start = holeIndices[i] * dim;
            end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
            list = linkedList(data, start, end, dim, false);
            if (list === list.next) list.steiner = true;
            queue.push(getLeftmost(list));
        }

        queue.sort(compareX);

        // process holes from left to right
        for (i = 0; i < queue.length; i++) {
            eliminateHole(queue[i], outerNode);
            outerNode = filterPoints(outerNode, outerNode.next);
        }

        return outerNode;
    }

    function compareX(a, b) {
        return a.x - b.x;
    }

    // find a bridge between vertices that connects hole with an outer ring and and link it
    function eliminateHole(hole, outerNode) {
        outerNode = findHoleBridge(hole, outerNode);
        if (outerNode) {
            var b = splitPolygon(outerNode, hole);
            filterPoints(b, b.next);
        }
    }

    // David Eberly's algorithm for finding a bridge between hole and outer polygon
    function findHoleBridge(hole, outerNode) {
        var p = outerNode,
            hx = hole.x,
            hy = hole.y,
            qx = -Infinity,
            m;

        // find a segment intersected by a ray from the hole's leftmost point to the left;
        // segment's endpoint with lesser x will be potential connection point
        do {
            if (hy <= p.y && hy >= p.next.y) {
                var x = p.x + ((hy - p.y) * (p.next.x - p.x)) / (p.next.y - p.y);
                if (x <= hx && x > qx) {
                    qx = x;
                    if (x === hx) {
                        if (hy === p.y) return p;
                        if (hy === p.next.y) return p.next;
                    }
                    m = p.x < p.next.x ? p : p.next;
                }
            }
            p = p.next;
        } while (p !== outerNode);

        if (!m) return null;

        if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint

        // look for points inside the triangle of hole point, segment intersection and endpoint;
        // if there are no points found, we have a valid connection;
        // otherwise choose the point of the minimum angle with the ray as connection point

        var stop = m,
            mx = m.x,
            my = m.y,
            tanMin = Infinity,
            tan;

        p = m.next;

        while (p !== stop) {
            if (
                hx >= p.x &&
                p.x >= mx &&
                pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)
            ) {
                tan = Math.abs(hy - p.y) / (hx - p.x); // tangential

                if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) {
                    m = p;
                    tanMin = tan;
                }
            }

            p = p.next;
        }

        return m;
    }

    // interlink polygon nodes in z-order
    function indexCurve(start, minX, minY, size) {
        var p = start;
        do {
            if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size);
            p.prevZ = p.prev;
            p.nextZ = p.next;
            p = p.next;
        } while (p !== start);

        p.prevZ.nextZ = null;
        p.prevZ = null;

        sortLinked(p);
    }

    // Simon Tatham's linked list merge sort algorithm
    // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
    function sortLinked(list) {
        var i,
            p,
            q,
            e,
            tail,
            numMerges,
            pSize,
            qSize,
            inSize = 1;

        do {
            p = list;
            list = null;
            tail = null;
            numMerges = 0;

            while (p) {
                numMerges++;
                q = p;
                pSize = 0;
                for (i = 0; i < inSize; i++) {
                    pSize++;
                    q = q.nextZ;
                    if (!q) break;
                }

                qSize = inSize;

                while (pSize > 0 || (qSize > 0 && q)) {
                    if (pSize === 0) {
                        e = q;
                        q = q.nextZ;
                        qSize--;
                    } else if (qSize === 0 || !q) {
                        e = p;
                        p = p.nextZ;
                        pSize--;
                    } else if (p.z <= q.z) {
                        e = p;
                        p = p.nextZ;
                        pSize--;
                    } else {
                        e = q;
                        q = q.nextZ;
                        qSize--;
                    }

                    if (tail) tail.nextZ = e;
                    else list = e;

                    e.prevZ = tail;
                    tail = e;
                }

                p = q;
            }

            tail.nextZ = null;
            inSize *= 2;
        } while (numMerges > 1);

        return list;
    }

    // z-order of a point given coords and size of the data bounding box
    function zOrder(x, y, minX, minY, size) {
        // coords are transformed into non-negative 15-bit integer range
        x = (32767 * (x - minX)) / size;
        y = (32767 * (y - minY)) / size;

        x = (x | (x << 8)) & 0x00ff00ff;
        x = (x | (x << 4)) & 0x0f0f0f0f;
        x = (x | (x << 2)) & 0x33333333;
        x = (x | (x << 1)) & 0x55555555;

        y = (y | (y << 8)) & 0x00ff00ff;
        y = (y | (y << 4)) & 0x0f0f0f0f;
        y = (y | (y << 2)) & 0x33333333;
        y = (y | (y << 1)) & 0x55555555;

        return x | (y << 1);
    }

    // find the leftmost node of a polygon ring
    function getLeftmost(start) {
        var p = start,
            leftmost = start;
        do {
            if (p.x < leftmost.x) leftmost = p;
            p = p.next;
        } while (p !== start);

        return leftmost;
    }

    // check if a point lies within a convex triangle
    function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
        return (
            (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
            (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
            (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0
        );
    }

    // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
    function isValidDiagonal(a, b) {
        return (
            a.next.i !== b.i &&
            a.prev.i !== b.i &&
            !intersectsPolygon(a, b) &&
            locallyInside(a, b) &&
            locallyInside(b, a) &&
            middleInside(a, b)
        );
    }

    // signed area of a triangle
    function area(p, q, r) {
        return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
    }

    // check if two points are equal
    function equals(p1, p2) {
        return p1.x === p2.x && p1.y === p2.y;
    }

    // check if two segments intersect
    function intersects(p1, q1, p2, q2) {
        if ((equals(p1, q1) && equals(p2, q2)) || (equals(p1, q2) && equals(p2, q1))) return true;
        return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;
    }

    // check if a polygon diagonal intersects any polygon segments
    function intersectsPolygon(a, b) {
        var p = a;
        do {
            if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b))
                return true;
            p = p.next;
        } while (p !== a);

        return false;
    }

    // check if a polygon diagonal is locally inside the polygon
    function locallyInside(a, b) {
        return area(a.prev, a, a.next) < 0
            ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0
            : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
    }

    // check if the middle point of a polygon diagonal is inside the polygon
    function middleInside(a, b) {
        var p = a,
            inside = false,
            px = (a.x + b.x) / 2,
            py = (a.y + b.y) / 2;
        do {
            if (p.y > py !== p.next.y > py && px < ((p.next.x - p.x) * (py - p.y)) / (p.next.y - p.y) + p.x)
                inside = !inside;
            p = p.next;
        } while (p !== a);

        return inside;
    }

    // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
    // if one belongs to the outer ring and another to a hole, it merges it into a single ring
    function splitPolygon(a, b) {
        var a2 = new Node(a.i, a.x, a.y),
            b2 = new Node(b.i, b.x, b.y),
            an = a.next,
            bp = b.prev;

        a.next = b;
        b.prev = a;

        a2.next = an;
        an.prev = a2;

        b2.next = a2;
        a2.prev = b2;

        bp.next = b2;
        b2.prev = bp;

        return b2;
    }

    // create a node and optionally link it with previous one (in a circular doubly linked list)
    function insertNode(i, x, y, last) {
        var p = new Node(i, x, y);

        if (!last) {
            p.prev = p;
            p.next = p;
        } else {
            p.next = last.next;
            p.prev = last;
            last.next.prev = p;
            last.next = p;
        }
        return p;
    }

    function removeNode(p) {
        p.next.prev = p.prev;
        p.prev.next = p.next;

        if (p.prevZ) p.prevZ.nextZ = p.nextZ;
        if (p.nextZ) p.nextZ.prevZ = p.prevZ;
    }

    function Node(i, x, y) {
        // vertice index in coordinates array
        this.i = i;

        // vertex coordinates
        this.x = x;
        this.y = y;

        // previous and next vertice nodes in a polygon ring
        this.prev = null;
        this.next = null;

        // z-order curve value
        this.z = null;

        // previous and next nodes in z-order
        this.prevZ = null;
        this.nextZ = null;

        // indicates whether this is a steiner point
        this.steiner = false;
    }

    // return a percentage difference between the polygon area and its triangulation area;
    // used to verify correctness of triangulation
    earcut.deviation = function (data, holeIndices, dim, triangles) {
        var hasHoles = holeIndices && holeIndices.length;
        var outerLen = hasHoles ? holeIndices[0] * dim : data.length;

        var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
        if (hasHoles) {
            for (var i = 0, len = holeIndices.length; i < len; i++) {
                var start = holeIndices[i] * dim;
                var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
                polygonArea -= Math.abs(signedArea(data, start, end, dim));
            }
        }

        var trianglesArea = 0;
        for (i = 0; i < triangles.length; i += 3) {
            var a = triangles[i] * dim;
            var b = triangles[i + 1] * dim;
            var c = triangles[i + 2] * dim;
            trianglesArea += Math.abs(
                (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1])
            );
        }

        return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea);
    };

    function signedArea(data, start, end, dim) {
        var sum = 0;
        for (var i = start, j = end - dim; i < end; i += dim) {
            sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
            j = i;
        }
        return sum;
    }

    // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
    earcut.flatten = function (data) {
        var dim = data[0][0].length,
            result = {
                vertices: [],
                holes: [],
                dimensions: dim,
            },
            holeIndex = 0;

        for (var i = 0; i < data.length; i++) {
            for (var j = 0; j < data[i].length; j++) {
                for (var d = 0; d < dim; d++) {
                    result.vertices.push(data[i][j][d]);
                }
            }
            if (i > 0) {
                holeIndex += data[i - 1].length;
                result.holes.push(holeIndex);
            }
        }
        return result;
    };

    var vs_s$2 = [
        'attribute vec4 a_Position;',
        'void main() {',
        'gl_Position = a_Position;',
        'gl_PointSize = 30.0;',
        '}',
    ].join('');

    var fs_s$2 = [
        'precision mediump float;',
        'uniform vec4 u_FragColor;',
        'void main() {',
        'gl_FragColor = u_FragColor;',
        '}',
    ].join('');

    function draw$3(gl, data, options) {
        if (!data) {
            return;
        }

        // gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

        var program = initShaders(gl, vs_s$2, fs_s$2);

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

        var halfCanvasWidth = gl.canvas.width / 2;
        var halfCanvasHeight = gl.canvas.height / 2;

        // Bind the buffer object to target
        gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());

        var a_Position = gl.getAttribLocation(program, 'a_Position');
        // Assign the buffer object to a_Position variable
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

        // Enable the assignment to a_Position variable
        gl.enableVertexAttribArray(a_Position);

        var uFragColor = gl.getUniformLocation(program, 'u_FragColor');

        var colored = getColorData(options.fillStyle || 'red');

        gl.uniform4f(uFragColor, colored[0] / 255, colored[1] / 255, colored[2] / 255, colored[3] / 255);

        gl.lineWidth(options.lineWidth || 1);

        var verticesArr = [];
        var trianglesArr = [];

        var maxSize = 65536;
        var indexOffset = 0;

        for (var i = 0, len = data.length; i < len; i++) {
            var flatten = earcut.flatten(data[i].geometry._coordinates || data[i].geometry.coordinates);
            var vertices = flatten.vertices;
            indexOffset = verticesArr.length / 2;
            for (var j = 0; j < vertices.length; j += 2) {
                vertices[j] = (vertices[j] - halfCanvasWidth) / halfCanvasWidth;
                vertices[j + 1] = (halfCanvasHeight - vertices[j + 1]) / halfCanvasHeight;
            }

            if ((verticesArr.length + vertices.length) / 2 > maxSize) {
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArr), gl.STATIC_DRAW);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(trianglesArr), gl.STATIC_DRAW);
                gl.drawElements(gl.TRIANGLES, trianglesArr.length, gl.UNSIGNED_SHORT, 0);
                verticesArr.length = 0;
                trianglesArr.length = 0;
                indexOffset = 0;
            }

            for (var j = 0; j < vertices.length; j++) {
                verticesArr.push(vertices[j]);
            }

            var triangles = earcut(vertices, flatten.holes, flatten.dimensions);
            for (var j = 0; j < triangles.length; j++) {
                trianglesArr.push(triangles[j] + indexOffset);
            }
        }

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArr), gl.STATIC_DRAW);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(trianglesArr), gl.STATIC_DRAW);
        gl.drawElements(gl.TRIANGLES, trianglesArr.length, gl.UNSIGNED_SHORT, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, null);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    }

    var polygon = {
        draw: draw$3,
    };

    /**
     * @author kyle / http://nikai.us/
     */
    var webglDrawSimple = {
        draw: function draw(gl, dataSet, options) {
            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;
            if (data.length > 0) {
                if (data[0].geometry.type == 'LineString') {
                    line.draw(gl, data, options);
                } else if (data[0].geometry.type == 'Polygon' || data[0].geometry.type == 'MultiPolygon') {
                    polygon.draw(gl, data, options);
                } else {
                    point.draw(gl, data, options);
                }
            }
        },
    };

    /**
     * get the center by the city name
     * @author kyle / http://nikai.us/
     */

    function getCenter(g) {
        var item = g.split('|');
        item[0] = item[0].split(',');
        return {
            lng: parseFloat(item[0][0]),
            lat: parseFloat(item[0][1]),
        };
    }

    var cityCenter = {
        getCenterByCityName: function getCenterByCityName(name) {
            for (var i = 0; i < citycenter.municipalities.length; i++) {
                if (citycenter.municipalities[i].n == name) {
                    return getCenter(citycenter.municipalities[i].g);
                }
            }

            var provinces = citycenter.provinces;
            for (var i = 0; i < provinces.length; i++) {
                if (provinces[i].n == name) {
                    return getCenter(provinces[i].g);
                }
                var cities = provinces[i].cities;
                for (var j = 0; j < cities.length; j++) {
                    if (cities[j].n == name) {
                        return getCenter(cities[j].g);
                    }
                }
            }
            return null;
        },
    };

    /**
     * 根据弧线的坐标节点数组
     */
    function getCurvePoints(points) {
        var curvePoints = [];
        for (var i = 0; i < points.length - 1; i++) {
            var p = getCurveByTwoPoints(points[i], points[i + 1]);
            if (p && p.length > 0) {
                curvePoints = curvePoints.concat(p);
            }
        }
        return curvePoints;
    }

    /**
     * 根据两点获取曲线坐标点数组
     * @param Point 起点
     * @param Point 终点
     */
    function getCurveByTwoPoints(obj1, obj2) {
        if (!obj1 || !obj2) {
            return null;
        }

        var B1 = function B1(x) {
            return 1 - 2 * x + x * x;
        };
        var B2 = function B2(x) {
            return 2 * x - 2 * x * x;
        };
        var B3 = function B3(x) {
            return x * x;
        };

        var curveCoordinates = [];

        var count = 40; // 曲线是由一些小的线段组成的,这个表示这个曲线所有到的折线的个数
        var isFuture = false;
        var t, h, h2, lat3, lng3, j, t2;
        var LnArray = [];
        var i = 0;
        var inc = 0;

        if (typeof obj2 == 'undefined') {
            if (typeof curveCoordinates != 'undefined') {
                curveCoordinates = [];
            }
            return;
        }

        var lat1 = parseFloat(obj1.lat);
        var lat2 = parseFloat(obj2.lat);
        var lng1 = parseFloat(obj1.lng);
        var lng2 = parseFloat(obj2.lng);

        // 计算曲线角度的方法
        if (lng2 > lng1) {
            if (parseFloat(lng2 - lng1) > 180) {
                if (lng1 < 0) {
                    lng1 = parseFloat(180 + 180 + lng1);
                }
            }
        }

        if (lng1 > lng2) {
            if (parseFloat(lng1 - lng2) > 180) {
                if (lng2 < 0) {
                    lng2 = parseFloat(180 + 180 + lng2);
                }
            }
        }
        j = 0;
        t2 = 0;
        if (lat2 == lat1) {
            t = 0;
            h = lng1 - lng2;
        } else if (lng2 == lng1) {
            t = Math.PI / 2;
            h = lat1 - lat2;
        } else {
            t = Math.atan((lat2 - lat1) / (lng2 - lng1));
            h = (lat2 - lat1) / Math.sin(t);
        }
        if (t2 == 0) {
            t2 = t + Math.PI / 5;
        }
        h2 = h / 2;
        lng3 = h2 * Math.cos(t2) + lng1;
        lat3 = h2 * Math.sin(t2) + lat1;

        for (i = 0; i < count + 1; i++) {
            curveCoordinates.push([
                lng1 * B1(inc) + lng3 * B2(inc) + lng2 * B3(inc),
                lat1 * B1(inc) + lat3 * B2(inc) + lat2 * B3(inc),
            ]);
            inc = inc + 1 / count;
        }
        return curveCoordinates;
    }

    var curve = {
        getPoints: getCurvePoints,
    };

    /* 
    FDEB algorithm implementation [www.win.tue.nl/~dholten/papers/forcebundles_eurovis.pdf].

    Author:  (github.com/upphiminn)
    2013

    */

    var ForceEdgeBundling = function ForceEdgeBundling() {
        var data_nodes = {},
            // {'nodeid':{'x':,'y':},..}
            data_edges = [],
            // [{'source':'nodeid1', 'target':'nodeid2'},..]
            compatibility_list_for_edge = [],
            subdivision_points_for_edge = [],
            K = 0.1,
            // global bundling constant controling edge stiffness
            S_initial = 0.1,
            // init. distance to move points
            P_initial = 1,
            // init. subdivision number
            P_rate = 2,
            // subdivision rate increase
            C = 6,
            // number of cycles to perform
            I_initial = 70,
            // init. number of iterations for cycle
            I_rate = 0.6666667,
            // rate at which iteration number decreases i.e. 2/3
            compatibility_threshold = 0.6,
            invers_quadratic_mode = false,
            eps = 1e-8;

        /*** Geometry Helper Methods ***/
        function vector_dot_product(p, q) {
            return p.x * q.x + p.y * q.y;
        }

        function edge_as_vector(P) {
            return {
                x: data_nodes[P.target].x - data_nodes[P.source].x,
                y: data_nodes[P.target].y - data_nodes[P.source].y,
            };
        }

        function edge_length(e) {
            return Math.sqrt(
                Math.pow(data_nodes[e.source].x - data_nodes[e.target].x, 2) +
                    Math.pow(data_nodes[e.source].y - data_nodes[e.target].y, 2)
            );
        }

        function custom_edge_length(e) {
            return Math.sqrt(Math.pow(e.source.x - e.target.x, 2) + Math.pow(e.source.y - e.target.y, 2));
        }

        function edge_midpoint(e) {
            var middle_x = (data_nodes[e.source].x + data_nodes[e.target].x) / 2.0;
            var middle_y = (data_nodes[e.source].y + data_nodes[e.target].y) / 2.0;
            return {
                x: middle_x,
                y: middle_y,
            };
        }

        function compute_divided_edge_length(e_idx) {
            var length = 0;
            for (var i = 1; i < subdivision_points_for_edge[e_idx].length; i++) {
                var segment_length = euclidean_distance(
                    subdivision_points_for_edge[e_idx][i],
                    subdivision_points_for_edge[e_idx][i - 1]
                );
                length += segment_length;
            }
            return length;
        }

        function euclidean_distance(p, q) {
            return Math.sqrt(Math.pow(p.x - q.x, 2) + Math.pow(p.y - q.y, 2));
        }

        function project_point_on_line(p, Q) {
            var L = Math.sqrt(
                (Q.target.x - Q.source.x) * (Q.target.x - Q.source.x) +
                    (Q.target.y - Q.source.y) * (Q.target.y - Q.source.y)
            );
            var r =
                ((Q.source.y - p.y) * (Q.source.y - Q.target.y) - (Q.source.x - p.x) * (Q.target.x - Q.source.x)) /
                (L * L);

            return {
                x: Q.source.x + r * (Q.target.x - Q.source.x),
                y: Q.source.y + r * (Q.target.y - Q.source.y),
            };
        }

        /*** ********************** ***/

        /*** Initialization Methods ***/
        function initialize_edge_subdivisions() {
            for (var i = 0; i < data_edges.length; i++) {
                if (P_initial == 1) subdivision_points_for_edge[i] = [];
                //0 subdivisions
                else {
                    subdivision_points_for_edge[i] = [];
                    subdivision_points_for_edge[i].push(data_nodes[data_edges[i].source]);
                    subdivision_points_for_edge[i].push(data_nodes[data_edges[i].target]);
                }
            }
        }

        function initialize_compatibility_lists() {
            for (var i = 0; i < data_edges.length; i++) {
                compatibility_list_for_edge[i] = [];
            } //0 compatible edges.
        }

        function filter_self_loops(edgelist) {
            var filtered_edge_list = [];
            for (var e = 0; e < edgelist.length; e++) {
                if (
                    data_nodes[edgelist[e].source].x != data_nodes[edgelist[e].target].x &&
                    data_nodes[edgelist[e].source].y != data_nodes[edgelist[e].target].y
                ) {
                    //or smaller than eps
                    filtered_edge_list.push(edgelist[e]);
                }
            }

            return filtered_edge_list;
        }
        /*** ********************** ***/

        /*** Force Calculation Methods ***/
        function apply_spring_force(e_idx, i, kP) {
            var prev = subdivision_points_for_edge[e_idx][i - 1];
            var next = subdivision_points_for_edge[e_idx][i + 1];
            var crnt = subdivision_points_for_edge[e_idx][i];

            var x = prev.x - crnt.x + next.x - crnt.x;
            var y = prev.y - crnt.y + next.y - crnt.y;

            x *= kP;
            y *= kP;

            return {
                x: x,
                y: y,
            };
        }

        function apply_electrostatic_force(e_idx, i, S) {
            var sum_of_forces = {
                x: 0,
                y: 0,
            };
            var compatible_edges_list = compatibility_list_for_edge[e_idx];

            for (var oe = 0; oe < compatible_edges_list.length; oe++) {
                var force = {
                    x:
                        subdivision_points_for_edge[compatible_edges_list[oe]][i].x -
                        subdivision_points_for_edge[e_idx][i].x,
                    y:
                        subdivision_points_for_edge[compatible_edges_list[oe]][i].y -
                        subdivision_points_for_edge[e_idx][i].y,
                };

                if (Math.abs(force.x) > eps || Math.abs(force.y) > eps) {
                    var diff =
                        1 /
                        Math.pow(
                            custom_edge_length({
                                source: subdivision_points_for_edge[compatible_edges_list[oe]][i],
                                target: subdivision_points_for_edge[e_idx][i],
                            }),
                            1
                        );

                    sum_of_forces.x += force.x * diff;
                    sum_of_forces.y += force.y * diff;
                }
            }
            return sum_of_forces;
        }

        function apply_resulting_forces_on_subdivision_points(e_idx, P, S) {
            var kP = K / (edge_length(data_edges[e_idx]) * (P + 1)); // kP=K/|P|(number of segments), where |P| is the initial length of edge P.
            // (length * (num of sub division pts - 1))
            var resulting_forces_for_subdivision_points = [
                {
                    x: 0,
                    y: 0,
                },
            ];
            for (var i = 1; i < P + 1; i++) {
                // exclude initial end points of the edge 0 and P+1
                var resulting_force = {
                    x: 0,
                    y: 0,
                };

                var spring_force = apply_spring_force(e_idx, i, kP);
                var electrostatic_force = apply_electrostatic_force(e_idx, i, S);

                resulting_force.x = S * (spring_force.x + electrostatic_force.x);
                resulting_force.y = S * (spring_force.y + electrostatic_force.y);

                resulting_forces_for_subdivision_points.push(resulting_force);
            }
            resulting_forces_for_subdivision_points.push({
                x: 0,
                y: 0,
            });
            return resulting_forces_for_subdivision_points;
        }
        /*** ********************** ***/

        /*** Edge Division Calculation Methods ***/
        function update_edge_divisions(P) {
            for (var e_idx = 0; e_idx < data_edges.length; e_idx++) {
                if (P == 1) {
                    subdivision_points_for_edge[e_idx].push(data_nodes[data_edges[e_idx].source]); // source
                    subdivision_points_for_edge[e_idx].push(edge_midpoint(data_edges[e_idx])); // mid point
                    subdivision_points_for_edge[e_idx].push(data_nodes[data_edges[e_idx].target]); // target
                } else {
                    var divided_edge_length = compute_divided_edge_length(e_idx);
                    var segment_length = divided_edge_length / (P + 1);
                    var current_segment_length = segment_length;
                    var new_subdivision_points = [];
                    new_subdivision_points.push(data_nodes[data_edges[e_idx].source]); //source

                    for (var i = 1; i < subdivision_points_for_edge[e_idx].length; i++) {
                        var old_segment_length = euclidean_distance(
                            subdivision_points_for_edge[e_idx][i],
                            subdivision_points_for_edge[e_idx][i - 1]
                        );

                        while (old_segment_length > current_segment_length) {
                            var percent_position = current_segment_length / old_segment_length;
                            var new_subdivision_point_x = subdivision_points_for_edge[e_idx][i - 1].x;
                            var new_subdivision_point_y = subdivision_points_for_edge[e_idx][i - 1].y;

                            new_subdivision_point_x +=
                                percent_position *
                                (subdivision_points_for_edge[e_idx][i].x - subdivision_points_for_edge[e_idx][i - 1].x);
                            new_subdivision_point_y +=
                                percent_position *
                                (subdivision_points_for_edge[e_idx][i].y - subdivision_points_for_edge[e_idx][i - 1].y);
                            new_subdivision_points.push({
                                x: new_subdivision_point_x,
                                y: new_subdivision_point_y,
                            });

                            old_segment_length -= current_segment_length;
                            current_segment_length = segment_length;
                        }
                        current_segment_length -= old_segment_length;
                    }
                    new_subdivision_points.push(data_nodes[data_edges[e_idx].target]); //target
                    subdivision_points_for_edge[e_idx] = new_subdivision_points;
                }
            }
        }
        /*** ********************** ***/

        /*** Edge compatibility measures ***/
        function angle_compatibility(P, Q) {
            var result = Math.abs(
                vector_dot_product(edge_as_vector(P), edge_as_vector(Q)) / (edge_length(P) * edge_length(Q))
            );
            return result;
        }

        function scale_compatibility(P, Q) {
            var lavg = (edge_length(P) + edge_length(Q)) / 2.0;
            var result =
                2.0 /
                (lavg / Math.min(edge_length(P), edge_length(Q)) + Math.max(edge_length(P), edge_length(Q)) / lavg);
            return result;
        }

        function position_compatibility(P, Q) {
            var lavg = (edge_length(P) + edge_length(Q)) / 2.0;
            var midP = {
                x: (data_nodes[P.source].x + data_nodes[P.target].x) / 2.0,
                y: (data_nodes[P.source].y + data_nodes[P.target].y) / 2.0,
            };
            var midQ = {
                x: (data_nodes[Q.source].x + data_nodes[Q.target].x) / 2.0,
                y: (data_nodes[Q.source].y + data_nodes[Q.target].y) / 2.0,
            };
            var result = lavg / (lavg + euclidean_distance(midP, midQ));
            return result;
        }

        function edge_visibility(P, Q) {
            var I0 = project_point_on_line(data_nodes[Q.source], {
                source: data_nodes[P.source],
                target: data_nodes[P.target],
            });
            var I1 = project_point_on_line(data_nodes[Q.target], {
                source: data_nodes[P.source],
                target: data_nodes[P.target],
            }); //send acutal edge points positions
            var midI = {
                x: (I0.x + I1.x) / 2.0,
                y: (I0.y + I1.y) / 2.0,
            };
            var midP = {
                x: (data_nodes[P.source].x + data_nodes[P.target].x) / 2.0,
                y: (data_nodes[P.source].y + data_nodes[P.target].y) / 2.0,
            };
            var result = Math.max(0, 1 - (2 * euclidean_distance(midP, midI)) / euclidean_distance(I0, I1));
            return result;
        }

        function visibility_compatibility(P, Q) {
            return Math.min(edge_visibility(P, Q), edge_visibility(Q, P));
        }

        function compatibility_score(P, Q) {
            var result =
                angle_compatibility(P, Q) *
                scale_compatibility(P, Q) *
                position_compatibility(P, Q) *
                visibility_compatibility(P, Q);

            return result;
        }

        function are_compatible(P, Q) {
            // console.log('compatibility ' + P.source +' - '+ P.target + ' and ' + Q.source +' '+ Q.target);
            return compatibility_score(P, Q) >= compatibility_threshold;
        }

        function compute_compatibility_lists() {
            for (var e = 0; e < data_edges.length - 1; e++) {
                for (var oe = e + 1; oe < data_edges.length; oe++) {
                    // don't want any duplicates
                    if (e == oe) continue;
                    else {
                        if (are_compatible(data_edges[e], data_edges[oe])) {
                            compatibility_list_for_edge[e].push(oe);
                            compatibility_list_for_edge[oe].push(e);
                        }
                    }
                }
            }
        }

        /*** ************************ ***/

        /*** Main Bundling Loop Methods ***/
        var forcebundle = function forcebundle() {
            var S = S_initial;
            var I = I_initial;
            var P = P_initial;

            initialize_edge_subdivisions();
            initialize_compatibility_lists();
            update_edge_divisions(P);
            compute_compatibility_lists();
            for (var cycle = 0; cycle < C; cycle++) {
                for (var iteration = 0; iteration < I; iteration++) {
                    var forces = [];
                    for (var edge = 0; edge < data_edges.length; edge++) {
                        forces[edge] = apply_resulting_forces_on_subdivision_points(edge, P, S);
                    }
                    for (var e = 0; e < data_edges.length; e++) {
                        for (var i = 0; i < P + 1; i++) {
                            subdivision_points_for_edge[e][i].x += forces[e][i].x;
                            subdivision_points_for_edge[e][i].y += forces[e][i].y;
                        }
                    }
                }
                //prepare for next cycle
                S = S / 2;
                P = P * 2;
                I = I_rate * I;

                update_edge_divisions(P);
                // console.log('C' + cycle);
                // console.log('P' + P);
                // console.log('S' + S);
            }
            return subdivision_points_for_edge;
        };
        /*** ************************ ***/

        /*** Getters/Setters Methods ***/
        forcebundle.nodes = function (nl) {
            if (arguments.length == 0) {
                return data_nodes;
            } else {
                data_nodes = nl;
            }
            return forcebundle;
        };

        forcebundle.edges = function (ll) {
            if (arguments.length == 0) {
                return data_edges;
            } else {
                data_edges = filter_self_loops(ll); //remove edges to from to the same point
            }
            return forcebundle;
        };

        forcebundle.bundling_stiffness = function (k) {
            if (arguments.length == 0) {
                return K;
            } else {
                K = k;
            }
            return forcebundle;
        };

        forcebundle.step_size = function (step) {
            if (arguments.length == 0) {
                return S_initial;
            } else {
                S_initial = step;
            }
            return forcebundle;
        };

        forcebundle.cycles = function (c) {
            if (arguments.length == 0) {
                return C;
            } else {
                C = c;
            }
            return forcebundle;
        };

        forcebundle.iterations = function (i) {
            if (arguments.length == 0) {
                return I_initial;
            } else {
                I_initial = i;
            }
            return forcebundle;
        };

        forcebundle.iterations_rate = function (i) {
            if (arguments.length == 0) {
                return I_rate;
            } else {
                I_rate = i;
            }
            return forcebundle;
        };

        forcebundle.subdivision_points_seed = function (p) {
            if (arguments.length == 0) {
                return P;
            } else {
                P = p;
            }
            return forcebundle;
        };

        forcebundle.subdivision_rate = function (r) {
            if (arguments.length == 0) {
                return P_rate;
            } else {
                P_rate = r;
            }
            return forcebundle;
        };

        forcebundle.compatbility_threshold = function (t) {
            if (arguments.length == 0) {
                return compatbility_threshold;
            } else {
                compatibility_threshold = t;
            }
            return forcebundle;
        };

        /*** ************************ ***/

        return forcebundle;
    };

    /**
     * @author kyle / http://nikai.us/
     */

    /**
     * Category
     * @param {Object} splitList:
     *   {
     *       other: 1,
     *       1: 2,
     *       2: 3,
     *       3: 4,
     *       4: 5,
     *       5: 6,
     *       6: 7
     *   }
     */
    function Category(splitList) {
        this.splitList = splitList || {
            other: 1,
        };
    }

    Category.prototype.get = function (count) {
        var splitList = this.splitList;

        var value = splitList['other'];

        for (var i in splitList) {
            if (count == i) {
                value = splitList[i];
                break;
            }
        }

        return value;
    };

    /**
     * 根据DataSet自动生成对应的splitList
     */
    Category.prototype.generateByDataSet = function (dataSet) {
        var colors = [
            'rgba(255, 255, 0, 0.8)',
            'rgba(253, 98, 104, 0.8)',
            'rgba(255, 146, 149, 0.8)',
            'rgba(255, 241, 193, 0.8)',
            'rgba(110, 176, 253, 0.8)',
            'rgba(52, 139, 251, 0.8)',
            'rgba(17, 102, 252, 0.8)',
        ];
        var data = dataSet.get();
        this.splitList = {};
        var count = 0;
        for (var i = 0; i < data.length; i++) {
            if (this.splitList[data[i].count] === undefined) {
                this.splitList[data[i].count] = colors[count];
                count++;
            }
            if (count >= colors.length - 1) {
                break;
            }
        }

        this.splitList['other'] = colors[colors.length - 1];
    };

    /**
     * @author kyle / http://nikai.us/
     */

    /**
     * Choropleth
     * @param {Object} splitList:
     *       [
     *           {
     *               start: 0,
     *               end: 2,
     *               value: randomColor()
     *           },{
     *               start: 2,
     *               end: 4,
     *               value: randomColor()
     *           },{
     *               start: 4,
     *               value: randomColor()
     *           }
     *       ];
     *
     */
    function Choropleth(splitList) {
        this.splitList = splitList || [
            {
                start: 0,
                value: 'red',
            },
        ];
    }

    Choropleth.prototype.get = function (count) {
        var splitList = this.splitList;

        var value = false;

        for (var i = 0; i < splitList.length; i++) {
            if (
                (splitList[i].start === undefined ||
                    (splitList[i].start !== undefined && count >= splitList[i].start)) &&
                (splitList[i].end === undefined || (splitList[i].end !== undefined && count < splitList[i].end))
            ) {
                value = splitList[i].value;
                break;
            }
        }

        return value;
    };

    /**
     * 根据DataSet自动生成对应的splitList
     */
    Choropleth.prototype.generateByDataSet = function (dataSet) {
        var min = dataSet.getMin('count');
        var max = dataSet.getMax('count');

        this.generateByMinMax(min, max);
    };

    /**
     * 根据DataSet自动生成对应的splitList
     */
    Choropleth.prototype.generateByMinMax = function (min, max) {
        var colors = [
            'rgba(255, 255, 0, 0.8)',
            'rgba(253, 98, 104, 0.8)',
            'rgba(255, 146, 149, 0.8)',
            'rgba(255, 241, 193, 0.8)',
            'rgba(110, 176, 253, 0.8)',
            'rgba(52, 139, 251, 0.8)',
            'rgba(17, 102, 252, 0.8)',
        ];
        var splitNum = (max - min) / 7;
        var index = min;
        this.splitList = [];
        var count = 0;
        while (index < max) {
            this.splitList.push({
                start: index,
                end: index + splitNum,
                value: colors[count],
            });
            count++;
            index += splitNum;
        }
    };

    /**
     * @author Mofei<http://www.zhuwenlong.com>
     */

    var MapHelper = (function () {
        function MapHelper(id, type, opt) {
            classCallCheck(this, MapHelper);

            if (!id || !type) {
                console.warn('id 和 type 为必填项');
                return false;
            }

            if (type == 'baidu') {
                if (!BMap) {
                    console.warn('请先引入百度地图JS API');
                    return false;
                }
            } else {
                console.warn('暂不支持你的地图类型');
            }
            this.type = type;
            var center = opt && opt.center ? opt.center : [106.962497, 38.208726];
            var zoom = opt && opt.zoom ? opt.zoom : 5;
            var map = (this.map = new BMap.Map(id, {
                enableMapClick: false,
            }));
            map.centerAndZoom(new BMap.Point(center[0], center[1]), zoom);
            map.enableScrollWheelZoom(true);

            map.setMapStyle({
                style: 'light',
            });
        }

        createClass(MapHelper, [
            {
                key: 'addLayer',
                value: function addLayer(datas, options) {
                    if (this.type == 'baidu') {
                        return new mapv.baiduMapLayer(this.map, dataSet, options);
                    }
                },
            },
            {
                key: 'getMap',
                value: function getMap() {
                    return this.map;
                },
            },
        ]);
        return MapHelper;
    })();

    /**
     * 一直覆盖在当前地图视野的Canvas对象
     *
     * @author nikai (@胖嘟嘟的骨头, nikai@baidu.com)
     *
     * @param
     * {
     *     map 地图实例对象
     * }
     */

    function CanvasLayer(options) {
        this.options = options || {};
        this.paneName = this.options.paneName || 'mapPane';
        this.context = this.options.context || '2d';
        this.zIndex = this.options.zIndex || 0;
        this.mixBlendMode = this.options.mixBlendMode || null;
        this.enableMassClear = this.options.enableMassClear;
        this._map = options.map;
        this._lastDrawTime = null;
        this.show();
    }

    var global$3 = typeof window === 'undefined' ? {} : window;

    if (global$3.BMap) {
        CanvasLayer.prototype = new BMap.Overlay();

        CanvasLayer.prototype.initialize = function (map) {
            this._map = map;
            var canvas = (this.canvas = document.createElement('canvas'));
            canvas.style.cssText =
                'position:absolute;' + 'left:0;' + 'top:0;' + 'z-index:' + this.zIndex + ';user-select:none;';
            canvas.style.mixBlendMode = this.mixBlendMode;
            this.adjustSize();
            map.getPanes()[this.paneName].appendChild(canvas);
            var that = this;
            map.addEventListener('resize', function () {
                that.adjustSize();
                that._draw();
            });
            return this.canvas;
        };

        CanvasLayer.prototype.adjustSize = function () {
            var size = this._map.getSize();
            var canvas = this.canvas;

            var devicePixelRatio = (this.devicePixelRatio = global$3.devicePixelRatio);

            canvas.width = size.width * devicePixelRatio;
            canvas.height = size.height * devicePixelRatio;
            if (this.context == '2d') {
                canvas.getContext(this.context).scale(devicePixelRatio, devicePixelRatio);
            }

            canvas.style.width = size.width + 'px';
            canvas.style.height = size.height + 'px';
        };

        CanvasLayer.prototype.draw = function () {
            var self = this;
            clearTimeout(self.timeoutID);
            self.timeoutID = setTimeout(function () {
                self._draw();
            }, 15);
        };

        CanvasLayer.prototype._draw = function () {
            var map = this._map;
            var size = map.getSize();
            var center = map.getCenter();
            if (center) {
                var pixel = map.pointToOverlayPixel(center);
                this.canvas.style.left = pixel.x - size.width / 2 + 'px';
                this.canvas.style.top = pixel.y - size.height / 2 + 'px';
                this.dispatchEvent('draw');
                this.options.update && this.options.update.call(this);
            }
        };

        CanvasLayer.prototype.getContainer = function () {
            return this.canvas;
        };

        CanvasLayer.prototype.show = function () {
            if (!this.canvas) {
                this._map.addOverlay(this);
            }
            this.canvas.style.display = 'block';
        };

        CanvasLayer.prototype.hide = function () {
            this.canvas.style.display = 'none';
            //this._map.removeOverlay(this);
        };

        CanvasLayer.prototype.setZIndex = function (zIndex) {
            this.canvas.style.zIndex = zIndex;
        };

        CanvasLayer.prototype.getZIndex = function () {
            return this.zIndex;
        };
    }

    /**
     * Tween.js - Licensed under the MIT license
     * https://github.com/tweenjs/tween.js
     * ----------------------------------------------
     *
     * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.
     * Thank you all, you're awesome!
     */

    var TWEEN =
        TWEEN ||
        (function () {
            var _tweens = [];

            return {
                getAll: function getAll() {
                    return _tweens;
                },

                removeAll: function removeAll() {
                    _tweens = [];
                },

                add: function add(tween) {
                    _tweens.push(tween);
                },

                remove: function remove(tween) {
                    var i = _tweens.indexOf(tween);

                    if (i !== -1) {
                        _tweens.splice(i, 1);
                    }
                },

                update: function update(time, preserve) {
                    if (_tweens.length === 0) {
                        return false;
                    }

                    var i = 0;

                    time = time !== undefined ? time : TWEEN.now();

                    while (i < _tweens.length) {
                        if (_tweens[i].update(time) || preserve) {
                            i++;
                        } else {
                            _tweens.splice(i, 1);
                        }
                    }

                    return true;
                },
            };
        })();

    // Include a performance.now polyfill.
    // In node.js, use process.hrtime.
    if (typeof window === 'undefined' && typeof process !== 'undefined') {
        TWEEN.now = function () {
            var time = process.hrtime();

            // Convert [seconds, nanoseconds] to milliseconds.
            return time[0] * 1000 + time[1] / 1000000;
        };
    }
    // In a browser, use window.performance.now if it is available.
    else if (
        typeof window !== 'undefined' &&
        window.performance !== undefined &&
        window.performance.now !== undefined
    ) {
        // This must be bound, because directly assigning this function
        // leads to an invocation exception in Chrome.
        TWEEN.now = window.performance.now.bind(window.performance);
    }
    // Use Date.now if it is available.
    else if (Date.now !== undefined) {
        TWEEN.now = Date.now;
    }
    // Otherwise, use 'new Date().getTime()'.
    else {
        TWEEN.now = function () {
            return new Date().getTime();
        };
    }

    TWEEN.Tween = function (object) {
        var _object = object;
        var _valuesStart = {};
        var _valuesEnd = {};
        var _valuesStartRepeat = {};
        var _duration = 1000;
        var _repeat = 0;
        var _repeatDelayTime;
        var _yoyo = false;
        var _isPlaying = false;
        var _reversed = false;
        var _delayTime = 0;
        var _startTime = null;
        var _easingFunction = TWEEN.Easing.Linear.None;
        var _interpolationFunction = TWEEN.Interpolation.Linear;
        var _chainedTweens = [];
        var _onStartCallback = null;
        var _onStartCallbackFired = false;
        var _onUpdateCallback = null;
        var _onCompleteCallback = null;
        var _onStopCallback = null;

        this.to = function (properties, duration) {
            _valuesEnd = properties;

            if (duration !== undefined) {
                _duration = duration;
            }

            return this;
        };

        this.start = function (time) {
            TWEEN.add(this);

            _isPlaying = true;

            _onStartCallbackFired = false;

            _startTime = time !== undefined ? time : TWEEN.now();
            _startTime += _delayTime;

            for (var property in _valuesEnd) {
                // Check if an Array was provided as property value
                if (_valuesEnd[property] instanceof Array) {
                    if (_valuesEnd[property].length === 0) {
                        continue;
                    }

                    // Create a local copy of the Array with the start value at the front
                    _valuesEnd[property] = [_object[property]].concat(_valuesEnd[property]);
                }

                // If `to()` specifies a property that doesn't exist in the source object,
                // we should not set that property in the object
                if (_object[property] === undefined) {
                    continue;
                }

                // Save the starting value.
                _valuesStart[property] = _object[property];

                if (_valuesStart[property] instanceof Array === false) {
                    _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings
                }

                _valuesStartRepeat[property] = _valuesStart[property] || 0;
            }

            return this;
        };

        this.stop = function () {
            if (!_isPlaying) {
                return this;
            }

            TWEEN.remove(this);
            _isPlaying = false;

            if (_onStopCallback !== null) {
                _onStopCallback.call(_object, _object);
            }

            this.stopChainedTweens();
            return this;
        };

        this.end = function () {
            this.update(_startTime + _duration);
            return this;
        };

        this.stopChainedTweens = function () {
            for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {
                _chainedTweens[i].stop();
            }
        };

        this.delay = function (amount) {
            _delayTime = amount;
            return this;
        };

        this.repeat = function (times) {
            _repeat = times;
            return this;
        };

        this.repeatDelay = function (amount) {
            _repeatDelayTime = amount;
            return this;
        };

        this.yoyo = function (yoyo) {
            _yoyo = yoyo;
            return this;
        };

        this.easing = function (easing) {
            _easingFunction = easing;
            return this;
        };

        this.interpolation = function (interpolation) {
            _interpolationFunction = interpolation;
            return this;
        };

        this.chain = function () {
            _chainedTweens = arguments;
            return this;
        };

        this.onStart = function (callback) {
            _onStartCallback = callback;
            return this;
        };

        this.onUpdate = function (callback) {
            _onUpdateCallback = callback;
            return this;
        };

        this.onComplete = function (callback) {
            _onCompleteCallback = callback;
            return this;
        };

        this.onStop = function (callback) {
            _onStopCallback = callback;
            return this;
        };

        this.update = function (time) {
            var property;
            var elapsed;
            var value;

            if (time < _startTime) {
                return true;
            }

            if (_onStartCallbackFired === false) {
                if (_onStartCallback !== null) {
                    _onStartCallback.call(_object, _object);
                }

                _onStartCallbackFired = true;
            }

            elapsed = (time - _startTime) / _duration;
            elapsed = elapsed > 1 ? 1 : elapsed;

            value = _easingFunction(elapsed);

            for (property in _valuesEnd) {
                // Don't update properties that do not exist in the source object
                if (_valuesStart[property] === undefined) {
                    continue;
                }

                var start = _valuesStart[property] || 0;
                var end = _valuesEnd[property];

                if (end instanceof Array) {
                    _object[property] = _interpolationFunction(end, value);
                } else {
                    // Parses relative end values with start as base (e.g.: +10, -3)
                    if (typeof end === 'string') {
                        if (end.charAt(0) === '+' || end.charAt(0) === '-') {
                            end = start + parseFloat(end);
                        } else {
                            end = parseFloat(end);
                        }
                    }

                    // Protect against non numeric properties.
                    if (typeof end === 'number') {
                        _object[property] = start + (end - start) * value;
                    }
                }
            }

            if (_onUpdateCallback !== null) {
                _onUpdateCallback.call(_object, value);
            }

            if (elapsed === 1) {
                if (_repeat > 0) {
                    if (isFinite(_repeat)) {
                        _repeat--;
                    }

                    // Reassign starting values, restart by making startTime = now
                    for (property in _valuesStartRepeat) {
                        if (typeof _valuesEnd[property] === 'string') {
                            _valuesStartRepeat[property] =
                                _valuesStartRepeat[property] + parseFloat(_valuesEnd[property]);
                        }

                        if (_yoyo) {
                            var tmp = _valuesStartRepeat[property];

                            _valuesStartRepeat[property] = _valuesEnd[property];
                            _valuesEnd[property] = tmp;
                        }

                        _valuesStart[property] = _valuesStartRepeat[property];
                    }

                    if (_yoyo) {
                        _reversed = !_reversed;
                    }

                    if (_repeatDelayTime !== undefined) {
                        _startTime = time + _repeatDelayTime;
                    } else {
                        _startTime = time + _delayTime;
                    }

                    return true;
                } else {
                    if (_onCompleteCallback !== null) {
                        _onCompleteCallback.call(_object, _object);
                    }

                    for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {
                        // Make the chained tweens start exactly at the time they should,
                        // even if the `update()` method was called way past the duration of the tween
                        _chainedTweens[i].start(_startTime + _duration);
                    }

                    return false;
                }
            }

            return true;
        };
    };

    TWEEN.Easing = {
        Linear: {
            None: function None(k) {
                return k;
            },
        },

        Quadratic: {
            In: function In(k) {
                return k * k;
            },

            Out: function Out(k) {
                return k * (2 - k);
            },

            InOut: function InOut(k) {
                if ((k *= 2) < 1) {
                    return 0.5 * k * k;
                }

                return -0.5 * (--k * (k - 2) - 1);
            },
        },

        Cubic: {
            In: function In(k) {
                return k * k * k;
            },

            Out: function Out(k) {
                return --k * k * k + 1;
            },

            InOut: function InOut(k) {
                if ((k *= 2) < 1) {
                    return 0.5 * k * k * k;
                }

                return 0.5 * ((k -= 2) * k * k + 2);
            },
        },

        Quartic: {
            In: function In(k) {
                return k * k * k * k;
            },

            Out: function Out(k) {
                return 1 - --k * k * k * k;
            },

            InOut: function InOut(k) {
                if ((k *= 2) < 1) {
                    return 0.5 * k * k * k * k;
                }

                return -0.5 * ((k -= 2) * k * k * k - 2);
            },
        },

        Quintic: {
            In: function In(k) {
                return k * k * k * k * k;
            },

            Out: function Out(k) {
                return --k * k * k * k * k + 1;
            },

            InOut: function InOut(k) {
                if ((k *= 2) < 1) {
                    return 0.5 * k * k * k * k * k;
                }

                return 0.5 * ((k -= 2) * k * k * k * k + 2);
            },
        },

        Sinusoidal: {
            In: function In(k) {
                return 1 - Math.cos((k * Math.PI) / 2);
            },

            Out: function Out(k) {
                return Math.sin((k * Math.PI) / 2);
            },

            InOut: function InOut(k) {
                return 0.5 * (1 - Math.cos(Math.PI * k));
            },
        },

        Exponential: {
            In: function In(k) {
                return k === 0 ? 0 : Math.pow(1024, k - 1);
            },

            Out: function Out(k) {
                return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
            },

            InOut: function InOut(k) {
                if (k === 0) {
                    return 0;
                }

                if (k === 1) {
                    return 1;
                }

                if ((k *= 2) < 1) {
                    return 0.5 * Math.pow(1024, k - 1);
                }

                return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
            },
        },

        Circular: {
            In: function In(k) {
                return 1 - Math.sqrt(1 - k * k);
            },

            Out: function Out(k) {
                return Math.sqrt(1 - --k * k);
            },

            InOut: function InOut(k) {
                if ((k *= 2) < 1) {
                    return -0.5 * (Math.sqrt(1 - k * k) - 1);
                }

                return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
            },
        },

        Elastic: {
            In: function In(k) {
                if (k === 0) {
                    return 0;
                }

                if (k === 1) {
                    return 1;
                }

                return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
            },

            Out: function Out(k) {
                if (k === 0) {
                    return 0;
                }

                if (k === 1) {
                    return 1;
                }

                return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1;
            },

            InOut: function InOut(k) {
                if (k === 0) {
                    return 0;
                }

                if (k === 1) {
                    return 1;
                }

                k *= 2;

                if (k < 1) {
                    return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);
                }

                return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1;
            },
        },

        Back: {
            In: function In(k) {
                var s = 1.70158;

                return k * k * ((s + 1) * k - s);
            },

            Out: function Out(k) {
                var s = 1.70158;

                return --k * k * ((s + 1) * k + s) + 1;
            },

            InOut: function InOut(k) {
                var s = 1.70158 * 1.525;

                if ((k *= 2) < 1) {
                    return 0.5 * (k * k * ((s + 1) * k - s));
                }

                return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
            },
        },

        Bounce: {
            In: function In(k) {
                return 1 - TWEEN.Easing.Bounce.Out(1 - k);
            },

            Out: function Out(k) {
                if (k < 1 / 2.75) {
                    return 7.5625 * k * k;
                } else if (k < 2 / 2.75) {
                    return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75;
                } else if (k < 2.5 / 2.75) {
                    return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375;
                } else {
                    return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375;
                }
            },

            InOut: function InOut(k) {
                if (k < 0.5) {
                    return TWEEN.Easing.Bounce.In(k * 2) * 0.5;
                }

                return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;
            },
        },
    };

    TWEEN.Interpolation = {
        Linear: function Linear(v, k) {
            var m = v.length - 1;
            var f = m * k;
            var i = Math.floor(f);
            var fn = TWEEN.Interpolation.Utils.Linear;

            if (k < 0) {
                return fn(v[0], v[1], f);
            }

            if (k > 1) {
                return fn(v[m], v[m - 1], m - f);
            }

            return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);
        },

        Bezier: function Bezier(v, k) {
            var b = 0;
            var n = v.length - 1;
            var pw = Math.pow;
            var bn = TWEEN.Interpolation.Utils.Bernstein;

            for (var i = 0; i <= n; i++) {
                b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);
            }

            return b;
        },

        CatmullRom: function CatmullRom(v, k) {
            var m = v.length - 1;
            var f = m * k;
            var i = Math.floor(f);
            var fn = TWEEN.Interpolation.Utils.CatmullRom;

            if (v[0] === v[m]) {
                if (k < 0) {
                    i = Math.floor((f = m * (1 + k)));
                }

                return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);
            } else {
                if (k < 0) {
                    return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);
                }

                if (k > 1) {
                    return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);
                }

                return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);
            }
        },

        Utils: {
            Linear: function Linear(p0, p1, t) {
                return (p1 - p0) * t + p0;
            },

            Bernstein: function Bernstein(n, i) {
                var fc = TWEEN.Interpolation.Utils.Factorial;

                return fc(n) / fc(i) / fc(n - i);
            },

            Factorial: (function () {
                var a = [1];

                return function (n) {
                    var s = 1;

                    if (a[n]) {
                        return a[n];
                    }

                    for (var i = n; i > 1; i--) {
                        s *= i;
                    }

                    a[n] = s;
                    return s;
                };
            })(),

            CatmullRom: function CatmullRom(p0, p1, p2, p3, t) {
                var v0 = (p2 - p0) * 0.5;
                var v1 = (p3 - p1) * 0.5;
                var t2 = t * t;
                var t3 = t * t2;

                return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
            },
        },
    };

    /**
     * @author Mofei Zhu<mapv@zhuwenlong.com>
     * This file is to draw text
     */

    var drawText = {
        draw: function draw(context, dataSet, options) {
            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;
            context.save();

            // set from options
            for (var key in options) {
                context[key] = options[key];
            }

            var offset = options.offset || {
                x: 0,
                y: 0,
            };

            var rects = [];

            var size = options._size || options.size;
            if (size) {
                context.font = 'bold ' + size + 'px Arial';
            } else {
                size = 12;
            }

            var textKey = options.textKey || 'text';

            context.textAlign = 'center';
            context.textBaseline = 'middle';

            if (options.avoid) {
                // 标注避让
                for (var i = 0, len = data.length; i < len; i++) {
                    var coordinates = data[i].geometry._coordinates || data[i].geometry.coordinates;
                    var x = coordinates[0] + offset.x;
                    var y = coordinates[1] + offset.y;
                    var text = data[i][textKey];
                    var textWidth = context.measureText(text).width;

                    // 根据文本宽度和高度调整x,y位置,使得绘制文本时候坐标点在文本中心点,这个计算出的是左上角坐标
                    var px = x - textWidth / 2;
                    var py = y - size / 2;

                    var rect = {
                        sw: {
                            x: px,
                            y: py + size,
                        },
                        ne: {
                            x: px + textWidth,
                            y: py,
                        },
                    };

                    if (!hasOverlay(rects, rect)) {
                        rects.push(rect);
                        px = px + textWidth / 2;
                        py = py + size / 2;
                        context.fillText(text, px, py);
                    }
                }
            } else {
                for (var i = 0, len = data.length; i < len; i++) {
                    var coordinates = data[i].geometry._coordinates || data[i].geometry.coordinates;
                    var x = coordinates[0] + offset.x;
                    var y = coordinates[1] + offset.y;
                    var text = data[i][textKey];
                    context.fillText(text, x, y);
                }
            }

            context.restore();
        },
    };

    /*
     *  当前文字区域和已有的文字区域是否有重叠部分
     */
    function hasOverlay(rects, overlay) {
        for (var i = 0; i < rects.length; i++) {
            if (isRectOverlay(rects[i], overlay)) {
                return true;
            }
        }
        return false;
    }

    //判断2个矩形是否有重叠部分
    function isRectOverlay(rect1, rect2) {
        //minx、miny 2个矩形右下角最小的x和y
        //maxx、maxy 2个矩形左上角最大的x和y
        var minx = Math.min(rect1.ne.x, rect2.ne.x);
        var miny = Math.min(rect1.sw.y, rect2.sw.y);
        var maxx = Math.max(rect1.sw.x, rect2.sw.x);
        var maxy = Math.max(rect1.ne.y, rect2.ne.y);
        if (minx > maxx && miny > maxy) {
            return true;
        }
        return false;
    }

    /**
     * @author Mofei Zhu<mapv@zhuwenlong.com>
     * This file is to draw text
     */

    var drawIcon = {
        draw: function draw(context, dataSet, options) {
            var data = dataSet instanceof DataSet ? dataSet.get() : dataSet;

            context.fillStyle = 'white';
            context.textAlign = 'center';
            context.textBaseline = 'middle';

            var offset = options.offset || {
                x: 0,
                y: 0,
            };

            // set from options
            // for (var key in options) {
            //     context[key] = options[key];
            // }
            // console.log(data)
            for (var i = 0, len = data.length; i < len; i++) {
                if (data[i].geometry) {
                    var deg = data[i].deg || options.deg;
                    var icon = data[i].icon || options.icon;
                    var coordinates = data[i].geometry._coordinates || data[i].geometry.coordinates;
                    var x = coordinates[0];
                    var y = coordinates[1];
                    if (deg) {
                        context.save();
                        context.translate(x, y);
                        context.rotate((deg * Math.PI) / 180);
                        context.translate(-x, -y);
                    }
                    var width = options._width || options.width || icon.width;
                    var height = options._height || options.height || icon.height;
                    x = x - width / 2 + offset.x;
                    y = y - height / 2 + offset.y;
                    if (
                        options.sx &&
                        options.sy &&
                        options.swidth &&
                        options.sheight &&
                        options.width &&
                        options.height
                    ) {
                        context.drawImage(
                            icon,
                            options.sx,
                            options.sy,
                            options.swidth,
                            options.sheight,
                            x,
                            y,
                            width,
                            height
                        );
                    } else if (options.width && options.height) {
                        context.drawImage(icon, x, y, width, height);
                    } else {
                        context.drawImage(icon, x, y);
                    }

                    if (deg) {
                        context.restore();
                    }
                }
            }
        },
    };

    /**
     * @author kyle / http://nikai.us/
     */

    if (typeof window !== 'undefined') {
        requestAnimationFrame(animate);
    }

    function animate(time) {
        requestAnimationFrame(animate);
        TWEEN.update(time);
    }

    var BaseLayer = (function () {
        function BaseLayer(map, dataSet, options) {
            classCallCheck(this, BaseLayer);

            if (!(dataSet instanceof DataSet)) {
                dataSet = new DataSet(dataSet);
            }

            this.dataSet = dataSet;
            this.map = map;
        }

        createClass(BaseLayer, [
            {
                key: 'getDefaultContextConfig',
                value: function getDefaultContextConfig() {
                    return {
                        globalAlpha: 1,
                        globalCompositeOperation: 'source-over',
                        imageSmoothingEnabled: true,
                        strokeStyle: '#000000',
                        fillStyle: '#000000',
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        shadowBlur: 0,
                        shadowColor: 'rgba(0, 0, 0, 0)',
                        lineWidth: 1,
                        lineCap: 'butt',
                        lineJoin: 'miter',
                        miterLimit: 10,
                        lineDashOffset: 0,
                        font: '10px sans-serif',
                        textAlign: 'start',
                        textBaseline: 'alphabetic',
                    };
                },
            },
            {
                key: 'initDataRange',
                value: function initDataRange(options) {
                    var self = this;

                    self.intensity = new Intensity({
                        maxSize: self.options.maxSize,
                        minSize: self.options.minSize,
                        gradient: self.options.gradient,
                        max: self.options.max || this.dataSet.getMax('count'),
                    });

                    self.category = new Category(self.options.splitList);
                    self.choropleth = new Choropleth(self.options.splitList);
                    if (self.options.splitList === undefined) {
                        self.category.generateByDataSet(this.dataSet);
                    }

                    if (self.options.splitList === undefined) {
                        var min = self.options.min || this.dataSet.getMin('count');
                        var max = self.options.max || this.dataSet.getMax('count');
                        self.choropleth.generateByMinMax(min, max);
                    }
                },
            },
            {
                key: 'getLegend',
                value: function getLegend(options) {
                    var draw = this.options.draw;
                    var legend = null;
                    if (self.options.draw == 'intensity' || self.options.draw == 'heatmap') {
                        return this.intensity.getLegend(options);
                    }
                },
            },
            {
                key: 'processData',
                value: function processData(data) {
                    var self = this;
                    var draw = self.options.draw;
                    if (
                        draw == 'bubble' ||
                        draw == 'intensity' ||
                        draw == 'category' ||
                        draw == 'choropleth' ||
                        draw == 'simple'
                    ) {
                        for (var i = 0; i < data.length; i++) {
                            var item = data[i];

                            if (self.options.draw == 'bubble') {
                                data[i]._size = self.intensity.getSize(item.count);
                            } else {
                                data[i]._size = undefined;
                            }

                            var styleType = 'fillStyle';

                            if (data[i].geometry.type === 'LineString' || self.options.styleType === 'stroke') {
                                styleType = 'strokeStyle';
                            }

                            if (self.options.draw == 'intensity') {
                                data[i][styleType] = self.intensity.getColor(item.count);
                            } else if (self.options.draw == 'category') {
                                data[i][styleType] = self.category.get(item.count);
                            } else if (self.options.draw == 'choropleth') {
                                data[i][styleType] = self.choropleth.get(item.count);
                            }
                        }
                    }
                },
            },
            {
                key: 'isEnabledTime',
                value: function isEnabledTime() {
                    var animationOptions = this.options.animation;

                    var flag = animationOptions && !(animationOptions.enabled === false);

                    return flag;
                },
            },
            {
                key: 'argCheck',
                value: function argCheck(options) {
                    if (options.draw == 'heatmap') {
                        if (options.strokeStyle) {
                            console.warn(
                                '[heatmap] options.strokeStyle is discard, pleause use options.strength [eg: options.strength = 0.1]'
                            );
                        }
                    }
                },
            },
            {
                key: 'drawContext',
                value: function drawContext(context, dataSet, options, nwPixel) {
                    var self = this;
                    switch (self.options.draw) {
                        case 'heatmap':
                            drawHeatmap.draw(context, dataSet, self.options);
                            break;
                        case 'grid':
                        case 'honeycomb':
                            self.options.offset = {
                                x: nwPixel.x,
                                y: nwPixel.y,
                            };
                            if (self.options.draw == 'grid') {
                                drawGrid.draw(context, dataSet, self.options);
                            } else {
                                drawHoneycomb.draw(context, dataSet, self.options);
                            }
                            break;
                        case 'text':
                            drawText.draw(context, dataSet, self.options);
                            break;
                        case 'icon':
                            drawIcon.draw(context, dataSet, self.options);
                            break;
                        case 'clip':
                            context.save();
                            context.fillStyle = self.options.fillStyle || 'rgba(0, 0, 0, 0.5)';
                            context.fillRect(0, 0, context.canvas.width, context.canvas.height);
                            drawSimple.draw(context, dataSet, self.options);
                            context.beginPath();
                            pathSimple.drawDataSet(context, dataSet, self.options);
                            context.clip();
                            clear(context);
                            context.restore();
                            break;
                        default:
                            if (self.options.context == 'webgl') {
                                webglDrawSimple.draw(
                                    self.canvasLayer.canvas.getContext('webgl'),
                                    dataSet,
                                    self.options
                                );
                            } else {
                                drawSimple.draw(context, dataSet, self.options);
                            }
                    }
                },
            },
            {
                key: 'isPointInPath',
                value: function isPointInPath(context, pixel) {
                    var context = this.canvasLayer.canvas.getContext(this.context);
                    var data = this.dataSet.get();
                    for (var i = 0; i < data.length; i++) {
                        context.beginPath();
                        pathSimple.draw(context, data[i], this.options);
                        if (
                            context.isPointInPath(
                                pixel.x * this.canvasLayer.devicePixelRatio,
                                pixel.y * this.canvasLayer.devicePixelRatio
                            )
                        ) {
                            return data[i];
                        }
                    }
                },
            },
            {
                key: 'clickEvent',
                value: function clickEvent(pixel, e) {
                    var dataItem = this.isPointInPath(this.getContext(), pixel);

                    if (dataItem) {
                        this.options.methods.click(dataItem, e);
                    } else {
                        this.options.methods.click(null, e);
                    }
                },
            },
            {
                key: 'mousemoveEvent',
                value: function mousemoveEvent(pixel, e) {
                    var dataItem = this.isPointInPath(this.getContext(), pixel);
                    if (dataItem) {
                        this.options.methods.mousemove(dataItem, e);
                    } else {
                        this.options.methods.mousemove(null, e);
                    }
                },

                /**
                 * obj.options
                 */
            },
            {
                key: 'update',
                value: function update(obj, isDraw) {
                    var self = this;
                    var _options = obj.options;
                    var options = self.options;
                    for (var i in _options) {
                        options[i] = _options[i];
                    }
                    self.init(options);
                    if (isDraw !== false) {
                        self.draw();
                    }
                },
            },
            {
                key: 'setOptions',
                value: function setOptions(options) {
                    var self = this;
                    self.init(options);
                    self.draw();
                },
            },
            {
                key: 'set',
                value: function set$$1(obj) {
                    var self = this;
                    var ctx = this.getContext();
                    var conf = this.getDefaultContextConfig();
                    for (var i in conf) {
                        ctx[i] = conf[i];
                    }
                    self.init(obj.options);
                    self.draw();
                },
            },
            {
                key: 'destroy',
                value: function destroy() {
                    this.unbindEvent();
                    this.hide();
                },
            },
            {
                key: 'initAnimator',
                value: function initAnimator() {
                    var self = this;
                    var animationOptions = self.options.animation;

                    if (self.options.draw == 'time' || self.isEnabledTime()) {
                        if (!animationOptions.stepsRange) {
                            animationOptions.stepsRange = {
                                start: this.dataSet.getMin('time') || 0,
                                end: this.dataSet.getMax('time') || 0,
                            };
                        }

                        this.steps = {
                            step: animationOptions.stepsRange.start,
                        };
                        self.animator = new TWEEN.Tween(this.steps)
                            .onUpdate(function () {
                                self._canvasUpdate(this.step);
                            })
                            .repeat(Infinity);

                        this.addAnimatorEvent();

                        var duration = animationOptions.duration * 1000 || 5000;

                        self.animator.to(
                            {
                                step: animationOptions.stepsRange.end,
                            },
                            duration
                        );
                        self.animator.start();
                    } else {
                        self.animator && self.animator.stop();
                    }
                },
            },
            {
                key: 'addAnimatorEvent',
                value: function addAnimatorEvent() {},
            },
            {
                key: 'animatorMovestartEvent',
                value: function animatorMovestartEvent() {
                    var animationOptions = this.options.animation;
                    if (this.isEnabledTime() && this.animator) {
                        this.steps.step = animationOptions.stepsRange.start;
                        this.animator.stop();
                    }
                },
            },
            {
                key: 'animatorMoveendEvent',
                value: function animatorMoveendEvent() {
                    if (this.isEnabledTime() && this.animator) {
                        this.animator.start();
                    }
                },
            },
        ]);
        return BaseLayer;
    })();

    var AnimationLayer = (function (_BaseLayer) {
        inherits(AnimationLayer, _BaseLayer);

        function AnimationLayer(map, dataSet, options) {
            classCallCheck(this, AnimationLayer);

            var _this = possibleConstructorReturn(
                this,
                (AnimationLayer.__proto__ || Object.getPrototypeOf(AnimationLayer)).call(this, map, dataSet, options)
            );

            _this.map = map;
            _this.options = options || {};
            _this.dataSet = dataSet;

            _this.init(options);

            var canvasLayer = new CanvasLayer({
                map: map,
                update: _this._canvasUpdate.bind(_this),
            });
            _this.transferToMercator();
            var self = _this;
            dataSet.on('change', function () {
                self.transferToMercator();
                canvasLayer.draw();
            });
            _this.ctx = canvasLayer.canvas.getContext('2d');

            _this.start();
            return _this;
        }

        createClass(AnimationLayer, [
            {
                key: 'init',
                value: function init(options) {
                    var self = this;
                    self.options = options;
                    this.initDataRange(options);
                    this.context = self.options.context || '2d';

                    if (self.options.zIndex) {
                        this.canvasLayer && this.canvasLayer.setZIndex(self.options.zIndex);
                    }

                    if (self.options.max) {
                        this.intensity.setMax(self.options.max);
                    }

                    if (self.options.min) {
                        this.intensity.setMin(self.options.min);
                    }

                    this.initAnimator();
                },

                // 经纬度左边转换为墨卡托坐标
            },
            {
                key: 'transferToMercator',
                value: function transferToMercator() {
                    var projection = this.map.getMapType().getProjection();

                    if (this.options.coordType !== 'bd09mc') {
                        var data = this.dataSet.get();
                        data = this.dataSet.transferCoordinate(
                            data,
                            function (coordinates) {
                                var pixel = projection.lngLatToPoint({
                                    lng: coordinates[0],
                                    lat: coordinates[1],
                                });
                                return [pixel.x, pixel.y];
                            },
                            'coordinates',
                            'coordinates_mercator'
                        );
                        this.dataSet._set(data);
                    }
                },
            },
            {
                key: '_canvasUpdate',
                value: function _canvasUpdate() {
                    var ctx = this.ctx;
                    if (!ctx) {
                        return;
                    }
                    //clear(ctx);
                    var map = this.map;
                    var zoomUnit = Math.pow(2, 18 - map.getZoom());
                    var projection = map.getMapType().getProjection();

                    var mcCenter = projection.lngLatToPoint(map.getCenter());
                    var nwMc = new BMap.Pixel(
                        mcCenter.x - (map.getSize().width / 2) * zoomUnit,
                        mcCenter.y + (map.getSize().height / 2) * zoomUnit
                    ); //左上角墨卡托坐标

                    clear(ctx);

                    var dataGetOptions = {
                        fromColumn: this.options.coordType == 'bd09mc' ? 'coordinates' : 'coordinates_mercator',
                        transferCoordinate: function transferCoordinate(coordinate) {
                            if (!coordinate) {
                                return;
                            }
                            var x = (coordinate[0] - nwMc.x) / zoomUnit;
                            var y = (nwMc.y - coordinate[1]) / zoomUnit;
                            return [x, y];
                        },
                    };

                    this.data = this.dataSet.get(dataGetOptions);

                    this.processData(this.data);

                    this.drawAnimation();
                },
            },
            {
                key: 'drawAnimation',
                value: function drawAnimation() {
                    var ctx = this.ctx;
                    var data = this.data;
                    if (!data) {
                        return;
                    }

                    ctx.save();
                    ctx.globalCompositeOperation = 'destination-out';
                    ctx.fillStyle = 'rgba(0, 0, 0, .1)';
                    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                    ctx.restore();

                    ctx.save();
                    if (this.options.shadowColor) {
                        ctx.shadowColor = this.options.shadowColor;
                    }

                    if (this.options.shadowBlur) {
                        ctx.shadowBlur = this.options.shadowBlur;
                    }

                    if (this.options.globalAlpha) {
                        ctx.globalAlpha = this.options.globalAlpha;
                    }

                    if (this.options.globalCompositeOperation) {
                        ctx.globalCompositeOperation = this.options.globalCompositeOperation;
                    }

                    var options = this.options;
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].geometry.type === 'Point') {
                            ctx.beginPath();
                            var maxSize = data[i].size || this.options.size;
                            var minSize = data[i].minSize || this.options.minSize || 0;
                            if (data[i]._size === undefined) {
                                data[i]._size = minSize;
                            }
                            ctx.arc(
                                data[i].geometry._coordinates[0],
                                data[i].geometry._coordinates[1],
                                data[i]._size,
                                0,
                                Math.PI * 2,
                                true
                            );
                            ctx.closePath();

                            data[i]._size++;

                            if (data[i]._size > maxSize) {
                                data[i]._size = minSize;
                            }
                            ctx.lineWidth = 1;
                            ctx.strokeStyle = data[i].strokeStyle || options.strokeStyle || 'yellow';
                            ctx.stroke();
                            var fillStyle = data[i].fillStyle || options.fillStyle;
                            if (fillStyle) {
                                ctx.fillStyle = fillStyle;
                                ctx.fill();
                            }
                        } else if (data[i].geometry.type === 'LineString') {
                            ctx.beginPath();
                            var size = data[i].size || this.options.size || 5;
                            var minSize = data[i].minSize || this.options.minSize || 0;
                            if (data[i]._index === undefined) {
                                data[i]._index = 0;
                            }
                            var index = data[i]._index;
                            ctx.arc(
                                data[i].geometry._coordinates[index][0],
                                data[i].geometry._coordinates[index][1],
                                size,
                                0,
                                Math.PI * 2,
                                true
                            );
                            ctx.closePath();

                            data[i]._index++;

                            if (data[i]._index >= data[i].geometry._coordinates.length) {
                                data[i]._index = 0;
                            }

                            ctx.lineWidth = options.lineWidth || 1;
                            var strokeStyle = data[i].strokeStyle || options.strokeStyle;
                            var fillStyle = data[i].fillStyle || options.fillStyle || 'yellow';
                            ctx.fillStyle = fillStyle;
                            ctx.fill();
                            if (strokeStyle) {
                                ctx.strokeStyle = strokeStyle;
                                ctx.stroke();
                            }
                        }
                    }
                    ctx.restore();
                },
            },
            {
                key: 'animate',
                value: function animate() {
                    this.drawAnimation();
                    var animateTime = this.options.animateTime || 100;
                    this.timeout = setTimeout(this.animate.bind(this), animateTime);
                },
            },
            {
                key: 'start',
                value: function start() {
                    this.stop();
                    this.animate();
                },
            },
            {
                key: 'stop',
                value: function stop() {
                    clearTimeout(this.timeout);
                },
            },
        ]);
        return AnimationLayer;
    })(BaseLayer);

    /**
     * @author kyle / http://nikai.us/
     */

    var Layer = (function (_BaseLayer) {
        inherits(Layer, _BaseLayer);

        function Layer(map, dataSet, options) {
            classCallCheck(this, Layer);

            var _this = possibleConstructorReturn(
                this,
                (Layer.__proto__ || Object.getPrototypeOf(Layer)).call(this, map, dataSet, options)
            );

            var self = _this;
            var data = null;
            options = options || {};

            self.init(options);
            self.argCheck(options);
            self.transferToMercator();

            var canvasLayer = (_this.canvasLayer = new CanvasLayer({
                map: map,
                context: _this.context,
                paneName: options.paneName,
                mixBlendMode: options.mixBlendMode,
                enableMassClear: options.enableMassClear,
                zIndex: options.zIndex,
                update: function update() {
                    self._canvasUpdate();
                },
            }));

            dataSet.on('change', function () {
                self.transferToMercator();
                canvasLayer.draw();
            });

            _this.clickEvent = _this.clickEvent.bind(_this);
            _this.mousemoveEvent = _this.mousemoveEvent.bind(_this);
            _this.bindEvent();

            return _this;
        }

        createClass(Layer, [
            {
                key: 'clickEvent',
                value: function clickEvent(e) {
                    var pixel = e.pixel;
                    get(Layer.prototype.__proto__ || Object.getPrototypeOf(Layer.prototype), 'clickEvent', this).call(
                        this,
                        pixel,
                        e
                    );
                },
            },
            {
                key: 'mousemoveEvent',
                value: function mousemoveEvent(e) {
                    var pixel = e.pixel;
                    get(
                        Layer.prototype.__proto__ || Object.getPrototypeOf(Layer.prototype),
                        'mousemoveEvent',
                        this
                    ).call(this, pixel, e);
                },
            },
            {
                key: 'bindEvent',
                value: function bindEvent(e) {
                    var map = this.map;

                    if (this.options.methods) {
                        if (this.options.methods.click) {
                            map.setDefaultCursor('default');
                            map.addEventListener('click', this.clickEvent);
                        }
                        if (this.options.methods.mousemove) {
                            map.addEventListener('mousemove', this.mousemoveEvent);
                        }
                    }
                },
            },
            {
                key: 'unbindEvent',
                value: function unbindEvent(e) {
                    var map = this.map;

                    if (this.options.methods) {
                        if (this.options.methods.click) {
                            map.removeEventListener('click', this.clickEvent);
                        }
                        if (this.options.methods.mousemove) {
                            map.removeEventListener('mousemove', this.mousemoveEvent);
                        }
                    }
                },

                // 经纬度左边转换为墨卡托坐标
            },
            {
                key: 'transferToMercator',
                value: function transferToMercator() {
                    var projection = this.map.getMapType().getProjection();

                    if (this.options.coordType !== 'bd09mc') {
                        var data = this.dataSet.get();
                        data = this.dataSet.transferCoordinate(
                            data,
                            function (coordinates) {
                                var pixel = projection.lngLatToPoint({
                                    lng: coordinates[0],
                                    lat: coordinates[1],
                                });
                                return [pixel.x, pixel.y];
                            },
                            'coordinates',
                            'coordinates_mercator'
                        );
                        this.dataSet._set(data);
                    }
                },
            },
            {
                key: 'getContext',
                value: function getContext() {
                    return this.canvasLayer.canvas.getContext(this.context);
                },
            },
            {
                key: '_canvasUpdate',
                value: function _canvasUpdate(time) {
                    if (!this.canvasLayer) {
                        return;
                    }

                    var self = this;

                    var animationOptions = self.options.animation;

                    var map = this.canvasLayer._map;

                    var zoomUnit = Math.pow(2, 18 - map.getZoom());
                    var projection = map.getMapType().getProjection();

                    var mcCenter = projection.lngLatToPoint(map.getCenter());
                    var nwMc = new BMap.Pixel(
                        mcCenter.x - (map.getSize().width / 2) * zoomUnit,
                        mcCenter.y + (map.getSize().height / 2) * zoomUnit
                    ); //左上角墨卡托坐标

                    var context = this.getContext();

                    if (self.isEnabledTime()) {
                        if (time === undefined) {
                            clear(context);
                            return;
                        }
                        if (this.context == '2d') {
                            context.save();
                            context.globalCompositeOperation = 'destination-out';
                            context.fillStyle = 'rgba(0, 0, 0, .1)';
                            context.fillRect(0, 0, context.canvas.width, context.canvas.height);
                            context.restore();
                        }
                    } else {
                        clear(context);
                    }

                    if (this.context == '2d') {
                        for (var key in self.options) {
                            context[key] = self.options[key];
                        }
                    } else {
                        context.clear(context.COLOR_BUFFER_BIT);
                    }

                    if (
                        (self.options.minZoom && map.getZoom() < self.options.minZoom) ||
                        (self.options.maxZoom && map.getZoom() > self.options.maxZoom)
                    ) {
                        return;
                    }

                    var scale = 1;
                    if (this.context != '2d') {
                        scale = this.canvasLayer.devicePixelRatio;
                    }

                    var dataGetOptions = {
                        fromColumn: self.options.coordType == 'bd09mc' ? 'coordinates' : 'coordinates_mercator',
                        transferCoordinate: function transferCoordinate(coordinate) {
                            var x = ((coordinate[0] - nwMc.x) / zoomUnit) * scale;
                            var y = ((nwMc.y - coordinate[1]) / zoomUnit) * scale;
                            return [x, y];
                        },
                    };

                    if (time !== undefined) {
                        dataGetOptions.filter = function (item) {
                            var trails = animationOptions.trails || 10;
                            if (time && item.time > time - trails && item.time < time) {
                                return true;
                            } else {
                                return false;
                            }
                        };
                    }

                    // get data from data set
                    var data = self.dataSet.get(dataGetOptions);

                    this.processData(data);

                    var nwPixel = map.pointToPixel(new BMap.Point(0, 0));

                    if (self.options.unit == 'm') {
                        if (self.options.size) {
                            self.options._size = self.options.size / zoomUnit;
                        }
                        if (self.options.width) {
                            self.options._width = self.options.width / zoomUnit;
                        }
                        if (self.options.height) {
                            self.options._height = self.options.height / zoomUnit;
                        }
                    } else {
                        self.options._size = self.options.size;
                        self.options._height = self.options.height;
                        self.options._width = self.options.width;
                    }

                    this.drawContext(context, data, self.options, nwPixel);

                    //console.timeEnd('draw');

                    //console.timeEnd('update')
                    self.options.updateCallback && self.options.updateCallback(time);
                },
            },
            {
                key: 'init',
                value: function init(options) {
                    var self = this;
                    self.options = options;
                    this.initDataRange(options);
                    this.context = self.options.context || '2d';

                    if (self.options.zIndex) {
                        this.canvasLayer && this.canvasLayer.setZIndex(self.options.zIndex);
                    }

                    if (self.options.max) {
                        this.intensity.setMax(self.options.max);
                    }

                    if (self.options.min) {
                        this.intensity.setMin(self.options.min);
                    }

                    this.initAnimator();
                },
            },
            {
                key: 'addAnimatorEvent',
                value: function addAnimatorEvent() {
                    this.map.addEventListener('movestart', this.animatorMovestartEvent.bind(this));
                    this.map.addEventListener('moveend', this.animatorMoveendEvent.bind(this));
                },
            },
            {
                key: 'show',
                value: function show() {
                    this.map.addOverlay(this.canvasLayer);
                },
            },
            {
                key: 'hide',
                value: function hide() {
                    this.map.removeOverlay(this.canvasLayer);
                },
            },
            {
                key: 'draw',
                value: function draw() {
                    this.canvasLayer.draw();
                },
            },
        ]);
        return Layer;
    })(BaseLayer);

    /**
     * Copyright 2012 Google Inc. All Rights Reserved.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    /**
     * @fileoverview Extends OverlayView to provide a canvas "Layer".
     * @author Brendan Kenny
     */

    /**
     * A map layer that provides a canvas over the slippy map and a callback
     * system for efficient animation. Requires canvas and CSS 2D transform
     * support.
     * @constructor
     * @extends google.maps.OverlayView
     * @param {CanvasLayerOptions=} opt_options Options to set in this CanvasLayer.
     */
    function CanvasLayer$2(opt_options) {
        /**
         * If true, canvas is in a map pane and the OverlayView is fully functional.
         * See google.maps.OverlayView.onAdd for more information.
         * @type {boolean}
         * @private
         */
        this.isAdded_ = false;

        /**
         * If true, each update will immediately schedule the next.
         * @type {boolean}
         * @private
         */
        this.isAnimated_ = false;

        /**
         * The name of the MapPane in which this layer will be displayed.
         * @type {string}
         * @private
         */
        this.paneName_ = CanvasLayer$2.DEFAULT_PANE_NAME_;

        /**
         * A user-supplied function called whenever an update is required. Null or
         * undefined if a callback is not provided.
         * @type {?function=}
         * @private
         */
        this.updateHandler_ = null;

        /**
         * A user-supplied function called whenever an update is required and the
         * map has been resized since the last update. Null or undefined if a
         * callback is not provided.
         * @type {?function}
         * @private
         */
        this.resizeHandler_ = null;

        /**
         * The LatLng coordinate of the top left of the current view of the map. Will
         * be null when this.isAdded_ is false.
         * @type {google.maps.LatLng}
         * @private
         */
        this.topLeft_ = null;

        /**
         * The map-pan event listener. Will be null when this.isAdded_ is false. Will
         * be null when this.isAdded_ is false.
         * @type {?function}
         * @private
         */
        this.centerListener_ = null;

        /**
         * The map-resize event listener. Will be null when this.isAdded_ is false.
         * @type {?function}
         * @private
         */
        this.resizeListener_ = null;

        /**
         * If true, the map size has changed and this.resizeHandler_ must be called
         * on the next update.
         * @type {boolean}
         * @private
         */
        this.needsResize_ = true;

        /**
         * A browser-defined id for the currently requested callback. Null when no
         * callback is queued.
         * @type {?number}
         * @private
         */
        this.requestAnimationFrameId_ = null;

        var canvas = document.createElement('canvas');
        canvas.style.position = 'absolute';
        canvas.style.top = 0;
        canvas.style.left = 0;
        canvas.style.pointerEvents = 'none';

        /**
         * The canvas element.
         * @type {!HTMLCanvasElement}
         */
        this.canvas = canvas;

        /**
         * The CSS width of the canvas, which may be different than the width of the
         * backing store.
         * @private {number}
         */
        this.canvasCssWidth_ = 300;

        /**
         * The CSS height of the canvas, which may be different than the height of
         * the backing store.
         * @private {number}
         */
        this.canvasCssHeight_ = 150;

        /**
         * A value for scaling the CanvasLayer resolution relative to the CanvasLayer
         * display size.
         * @private {number}
         */
        this.resolutionScale_ = 1;

        /**
         * Simple bind for functions with no args for bind-less browsers (Safari).
         * @param {Object} thisArg The this value used for the target function.
         * @param {function} func The function to be bound.
         */
        function simpleBindShim(thisArg, func) {
            return function () {
                func.apply(thisArg);
            };
        }

        /**
         * A reference to this.repositionCanvas_ with this bound as its this value.
         * @type {function}
         * @private
         */
        this.repositionFunction_ = simpleBindShim(this, this.repositionCanvas_);

        /**
         * A reference to this.resize_ with this bound as its this value.
         * @type {function}
         * @private
         */
        this.resizeFunction_ = simpleBindShim(this, this.resize_);

        /**
         * A reference to this.update_ with this bound as its this value.
         * @type {function}
         * @private
         */
        this.requestUpdateFunction_ = simpleBindShim(this, this.update_);

        // set provided options, if any
        if (opt_options) {
            this.setOptions(opt_options);
        }
    }

    var global$4 = typeof window === 'undefined' ? {} : window;

    if (global$4.google && global$4.google.maps) {
        CanvasLayer$2.prototype = new google.maps.OverlayView();

        /**
         * The default MapPane to contain the canvas.
         * @type {string}
         * @const
         * @private
         */
        CanvasLayer$2.DEFAULT_PANE_NAME_ = 'overlayLayer';

        /**
         * Transform CSS property name, with vendor prefix if required. If browser
         * does not support transforms, property will be ignored.
         * @type {string}
         * @const
         * @private
         */
        CanvasLayer$2.CSS_TRANSFORM_ = (function () {
            var div = document.createElement('div');
            var transformProps = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
            for (var i = 0; i < transformProps.length; i++) {
                var prop = transformProps[i];
                if (div.style[prop] !== undefined) {
                    return prop;
                }
            }

            // return unprefixed version by default
            return transformProps[0];
        })();

        /**
         * The requestAnimationFrame function, with vendor-prefixed or setTimeout-based
         * fallbacks. MUST be called with window as thisArg.
         * @type {function}
         * @param {function} callback The function to add to the frame request queue.
         * @return {number} The browser-defined id for the requested callback.
         * @private
         */
        CanvasLayer$2.prototype.requestAnimFrame_ =
            global$4.requestAnimationFrame ||
            global$4.webkitRequestAnimationFrame ||
            global$4.mozRequestAnimationFrame ||
            global$4.oRequestAnimationFrame ||
            global$4.msRequestAnimationFrame ||
            function (callback) {
                return global$4.setTimeout(callback, 1000 / 60);
            };

        /**
         * The cancelAnimationFrame function, with vendor-prefixed fallback. Does not
         * fall back to clearTimeout as some platforms implement requestAnimationFrame
         * but not cancelAnimationFrame, and the cost is an extra frame on onRemove.
         * MUST be called with window as thisArg.
         * @type {function}
         * @param {number=} requestId The id of the frame request to cancel.
         * @private
         */
        CanvasLayer$2.prototype.cancelAnimFrame_ =
            global$4.cancelAnimationFrame ||
            global$4.webkitCancelAnimationFrame ||
            global$4.mozCancelAnimationFrame ||
            global$4.oCancelAnimationFrame ||
            global$4.msCancelAnimationFrame ||
            function (requestId) {};

        /**
         * Sets any options provided. See CanvasLayerOptions for more information.
         * @param {CanvasLayerOptions} options The options to set.
         */
        CanvasLayer$2.prototype.setOptions = function (options) {
            if (options.animate !== undefined) {
                this.setAnimate(options.animate);
            }

            if (options.paneName !== undefined) {
                this.setPaneName(options.paneName);
            }

            if (options.updateHandler !== undefined) {
                this.setUpdateHandler(options.updateHandler);
            }

            if (options.resizeHandler !== undefined) {
                this.setResizeHandler(options.resizeHandler);
            }

            if (options.resolutionScale !== undefined) {
                this.setResolutionScale(options.resolutionScale);
            }

            if (options.map !== undefined) {
                this.setMap(options.map);
            }
        };

        /**
         * Set the animated state of the layer. If true, updateHandler will be called
         * repeatedly, once per frame. If false, updateHandler will only be called when
         * a map property changes that could require the canvas content to be redrawn.
         * @param {boolean} animate Whether the canvas is animated.
         */
        CanvasLayer$2.prototype.setAnimate = function (animate) {
            this.isAnimated_ = !!animate;

            if (this.isAnimated_) {
                this.scheduleUpdate();
            }
        };

        /**
         * @return {boolean} Whether the canvas is animated.
         */
        CanvasLayer$2.prototype.isAnimated = function () {
            return this.isAnimated_;
        };

        /**
         * Set the MapPane in which this layer will be displayed, by name. See
         * {@code google.maps.MapPanes} for the panes available.
         * @param {string} paneName The name of the desired MapPane.
         */
        CanvasLayer$2.prototype.setPaneName = function (paneName) {
            this.paneName_ = paneName;

            this.setPane_();
        };

        /**
         * @return {string} The name of the current container pane.
         */
        CanvasLayer$2.prototype.getPaneName = function () {
            return this.paneName_;
        };

        /**
         * Adds the canvas to the specified container pane. Since this is guaranteed to
         * execute only after onAdd is called, this is when paneName's existence is
         * checked (and an error is thrown if it doesn't exist).
         * @private
         */
        CanvasLayer$2.prototype.setPane_ = function () {
            if (!this.isAdded_) {
                return;
            }

            // onAdd has been called, so panes can be used
            var panes = this.getPanes();
            if (!panes[this.paneName_]) {
                throw new Error('"' + this.paneName_ + '" is not a valid MapPane name.');
            }

            panes[this.paneName_].appendChild(this.canvas);
        };

        /**
         * Set a function that will be called whenever the parent map and the overlay's
         * canvas have been resized. If opt_resizeHandler is null or unspecified, any
         * existing callback is removed.
         * @param {?function=} opt_resizeHandler The resize callback function.
         */
        CanvasLayer$2.prototype.setResizeHandler = function (opt_resizeHandler) {
            this.resizeHandler_ = opt_resizeHandler;
        };

        /**
         * Sets a value for scaling the canvas resolution relative to the canvas
         * display size. This can be used to save computation by scaling the backing
         * buffer down, or to support high DPI devices by scaling it up (by e.g.
         * window.devicePixelRatio).
         * @param {number} scale
         */
        CanvasLayer$2.prototype.setResolutionScale = function (scale) {
            if (typeof scale === 'number') {
                this.resolutionScale_ = scale;
                this.resize_();
            }
        };

        /**
         * Set a function that will be called when a repaint of the canvas is required.
         * If opt_updateHandler is null or unspecified, any existing callback is
         * removed.
         * @param {?function=} opt_updateHandler The update callback function.
         */
        CanvasLayer$2.prototype.setUpdateHandler = function (opt_updateHandler) {
            this.updateHandler_ = opt_updateHandler;
        };

        /**
         * @inheritDoc
         */
        CanvasLayer$2.prototype.onAdd = function () {
            if (this.isAdded_) {
                return;
            }

            this.isAdded_ = true;
            this.setPane_();

            this.resizeListener_ = google.maps.event.addListener(this.getMap(), 'resize', this.resizeFunction_);
            this.centerListener_ = google.maps.event.addListener(
                this.getMap(),
                'center_changed',
                this.repositionFunction_
            );

            this.resize_();
            this.repositionCanvas_();
        };

        /**
         * @inheritDoc
         */
        CanvasLayer$2.prototype.onRemove = function () {
            if (!this.isAdded_) {
                return;
            }

            this.isAdded_ = false;
            this.topLeft_ = null;

            // remove canvas and listeners for pan and resize from map
            this.canvas.parentElement.removeChild(this.canvas);
            if (this.centerListener_) {
                google.maps.event.removeListener(this.centerListener_);
                this.centerListener_ = null;
            }
            if (this.resizeListener_) {
                google.maps.event.removeListener(this.resizeListener_);
                this.resizeListener_ = null;
            }

            // cease canvas update callbacks
            if (this.requestAnimationFrameId_) {
                this.cancelAnimFrame_.call(global$4, this.requestAnimationFrameId_);
                this.requestAnimationFrameId_ = null;
            }
        };

        /**
         * The internal callback for resize events that resizes the canvas to keep the
         * map properly covered.
         * @private
         */
        CanvasLayer$2.prototype.resize_ = function () {
            if (!this.isAdded_) {
                return;
            }

            var map = this.getMap();
            var mapWidth = map.getDiv().offsetWidth;
            var mapHeight = map.getDiv().offsetHeight;

            var newWidth = mapWidth * this.resolutionScale_;
            var newHeight = mapHeight * this.resolutionScale_;
            var oldWidth = this.canvas.width;
            var oldHeight = this.canvas.height;

            // resizing may allocate a new back buffer, so do so conservatively
            if (oldWidth !== newWidth || oldHeight !== newHeight) {
                this.canvas.width = newWidth;
                this.canvas.height = newHeight;

                this.needsResize_ = true;
                this.scheduleUpdate();
            }

            // reset styling if new sizes don't match; resize of data not needed
            if (this.canvasCssWidth_ !== mapWidth || this.canvasCssHeight_ !== mapHeight) {
                this.canvasCssWidth_ = mapWidth;
                this.canvasCssHeight_ = mapHeight;
                this.canvas.style.width = mapWidth + 'px';
                this.canvas.style.height = mapHeight + 'px';
            }
        };

        /**
         * @inheritDoc
         */
        CanvasLayer$2.prototype.draw = function () {
            this.repositionCanvas_();
        };

        /**
         * Internal callback for map view changes. Since the Maps API moves the overlay
         * along with the map, this function calculates the opposite translation to
         * keep the canvas in place.
         * @private
         */
        CanvasLayer$2.prototype.repositionCanvas_ = function () {
            // TODO(bckenny): *should* only be executed on RAF, but in current browsers
            //     this causes noticeable hitches in map and overlay relative
            //     positioning.

            var map = this.getMap();

            // topLeft can't be calculated from map.getBounds(), because bounds are
            // clamped to -180 and 180 when completely zoomed out. Instead, calculate
            // left as an offset from the center, which is an unwrapped LatLng.
            var top = map.getBounds().getNorthEast().lat();
            var center = map.getCenter();
            var scale = Math.pow(2, map.getZoom());
            var left = center.lng() - (this.canvasCssWidth_ * 180) / (256 * scale);
            this.topLeft_ = new google.maps.LatLng(top, left);

            // Canvas position relative to draggable map's container depends on
            // overlayView's projection, not the map's. Have to use the center of the
            // map for this, not the top left, for the same reason as above.
            var projection = this.getProjection();
            var divCenter = projection.fromLatLngToDivPixel(center);
            var offsetX = -Math.round(this.canvasCssWidth_ / 2 - divCenter.x);
            var offsetY = -Math.round(this.canvasCssHeight_ / 2 - divCenter.y);
            this.canvas.style[CanvasLayer$2.CSS_TRANSFORM_] = 'translate(' + offsetX + 'px,' + offsetY + 'px)';

            this.scheduleUpdate();
        };

        /**
         * Internal callback that serves as main animation scheduler via
         * requestAnimationFrame. Calls resize and update callbacks if set, and
         * schedules the next frame if overlay is animated.
         * @private
         */
        CanvasLayer$2.prototype.update_ = function () {
            this.requestAnimationFrameId_ = null;

            if (!this.isAdded_) {
                return;
            }

            if (this.isAnimated_) {
                this.scheduleUpdate();
            }

            if (this.needsResize_ && this.resizeHandler_) {
                this.needsResize_ = false;
                this.resizeHandler_();
            }

            if (this.updateHandler_) {
                this.updateHandler_();
            }
        };

        /**
         * A convenience method to get the current LatLng coordinate of the top left of
         * the current view of the map.
         * @return {google.maps.LatLng} The top left coordinate.
         */
        CanvasLayer$2.prototype.getTopLeft = function () {
            return this.topLeft_;
        };

        /**
         * Schedule a requestAnimationFrame callback to updateHandler. If one is
         * already scheduled, there is no effect.
         */
        CanvasLayer$2.prototype.scheduleUpdate = function () {
            if (this.isAdded_ && !this.requestAnimationFrameId_) {
                this.requestAnimationFrameId_ = this.requestAnimFrame_.call(global$4, this.requestUpdateFunction_);
            }
        };
    }

    /**
     * @author kyle / http://nikai.us/
     */

    var Layer$2 = (function (_BaseLayer) {
        inherits(Layer, _BaseLayer);

        function Layer(map, dataSet, options) {
            classCallCheck(this, Layer);

            var _this = possibleConstructorReturn(
                this,
                (Layer.__proto__ || Object.getPrototypeOf(Layer)).call(this, map, dataSet, options)
            );

            var self = _this;
            var data = null;
            options = options || {};

            self.init(options);
            self.argCheck(options);

            var canvasLayerOptions = {
                map: map,
                animate: false,
                updateHandler: function updateHandler() {
                    self._canvasUpdate();
                },
                resolutionScale: resolutionScale,
            };

            var canvasLayer = (_this.canvasLayer = new CanvasLayer$2(canvasLayerOptions));

            _this.clickEvent = _this.clickEvent.bind(_this);
            _this.mousemoveEvent = _this.mousemoveEvent.bind(_this);
            _this.bindEvent();
            return _this;
        }

        createClass(Layer, [
            {
                key: 'clickEvent',
                value: function clickEvent(e) {
                    var pixel = e.pixel;
                    get(Layer.prototype.__proto__ || Object.getPrototypeOf(Layer.prototype), 'clickEvent', this).call(
                        this,
                        pixel,
                        e
                    );
                },
            },
            {
                key: 'mousemoveEvent',
                value: function mousemoveEvent(e) {
                    var pixel = e.pixel;
                    get(
                        Layer.prototype.__proto__ || Object.getPrototypeOf(Layer.prototype),
                        'mousemoveEvent',
                        this
                    ).call(this, pixel, e);
                },
            },
            {
                key: 'bindEvent',
                value: function bindEvent(e) {
                    var map = this.map;

                    if (this.options.methods) {
                        if (this.options.methods.click) {
                            map.setDefaultCursor('default');
                            map.addListener('click', this.clickEvent);
                        }
                        if (this.options.methods.mousemove) {
                            map.addListener('mousemove', this.mousemoveEvent);
                        }
                    }
                },
            },
            {
                key: 'unbindEvent',
                value: function unbindEvent(e) {
                    var map = this.map;

                    if (this.options.methods) {
                        if (this.options.methods.click) {
                            map.removeListener('click', this.clickEvent);
                        }
                        if (this.options.methods.mousemove) {
                            map.removeListener('mousemove', this.mousemoveEvent);
                        }
                    }
                },
            },
            {
                key: 'getContext',
                value: function getContext() {
                    return this.canvasLayer.canvas.getContext(this.context);
                },
            },
            {
                key: '_canvasUpdate',
                value: function _canvasUpdate(time) {
                    if (!this.canvasLayer) {
                        return;
                    }

                    var self = this;

                    var animationOptions = self.options.animation;

                    var context = this.getContext();

                    if (self.isEnabledTime()) {
                        if (time === undefined) {
                            clear(context);
                            return;
                        }
                        if (this.context == '2d') {
                            context.save();
                            context.globalCompositeOperation = 'destination-out';
                            context.fillStyle = 'rgba(0, 0, 0, .1)';
                            context.fillRect(0, 0, context.canvas.width, context.canvas.height);
                            context.restore();
                        }
                    } else {
                        clear(context);
                    }

                    if (this.context == '2d') {
                        for (var key in self.options) {
                            context[key] = self.options[key];
                        }
                    } else {
                        context.clear(context.COLOR_BUFFER_BIT);
                    }

                    if (
                        (self.options.minZoom && map.getZoom() < self.options.minZoom) ||
                        (self.options.maxZoom && map.getZoom() > self.options.maxZoom)
                    ) {
                        return;
                    }

                    var scale = 1;
                    if (this.context != '2d') {
                        scale = this.canvasLayer.devicePixelRatio;
                    }

                    var map = this.map;
                    var mapProjection = map.getProjection();
                    var scale = Math.pow(2, map.zoom) * resolutionScale;
                    var offset = mapProjection.fromLatLngToPoint(this.canvasLayer.getTopLeft());
                    var dataGetOptions = {
                        //fromColumn: self.options.coordType == 'bd09mc' ? 'coordinates' : 'coordinates_mercator',
                        transferCoordinate: function transferCoordinate(coordinate) {
                            var latLng = new google.maps.LatLng(coordinate[1], coordinate[0]);
                            var worldPoint = mapProjection.fromLatLngToPoint(latLng);
                            var pixel = {
                                x: (worldPoint.x - offset.x) * scale,
                                y: (worldPoint.y - offset.y) * scale,
                            };
                            return [pixel.x, pixel.y];
                        },
                    };

                    if (time !== undefined) {
                        dataGetOptions.filter = function (item) {
                            var trails = animationOptions.trails || 10;
                            if (time && item.time > time - trails && item.time < time) {
                                return true;
                            } else {
                                return false;
                            }
                        };
                    }

                    // get data from data set
                    var data = self.dataSet.get(dataGetOptions);

                    this.processData(data);

                    var latLng = new google.maps.LatLng(0, 0);
                    var worldPoint = mapProjection.fromLatLngToPoint(latLng);
                    var pixel = {
                        x: (worldPoint.x - offset.x) * scale,
                        y: (worldPoint.y - offset.y) * scale,
                    };

                    if (self.options.unit == 'm' && self.options.size) {
                        self.options._size = self.options.size / zoomUnit;
                    } else {
                        self.options._size = self.options.size;
                    }

                    this.drawContext(context, new DataSet(data), self.options, pixel);

                    //console.timeEnd('draw');

                    //console.timeEnd('update')
                    self.options.updateCallback && self.options.updateCallback(time);
                },
            },
            {
                key: 'init',
                value: function init(options) {
                    var self = this;

                    self.options = options;

                    this.initDataRange(options);

                    this.context = self.options.context || '2d';

                    if (self.options.zIndex) {
                        this.canvasLayer && this.canvasLayer.setZIndex(self.options.zIndex);
                    }

                    this.initAnimator();
                },
            },
            {
                key: 'addAnimatorEvent',
                value: function addAnimatorEvent() {
                    this.map.addListener('movestart', this.animatorMovestartEvent.bind(this));
                    this.map.addListener('moveend', this.animatorMoveendEvent.bind(this));
                },
            },
            {
                key: 'show',
                value: function show() {
                    this.map.addOverlay(this.canvasLayer);
                },
            },
            {
                key: 'hide',
                value: function hide() {
                    this.map.removeOverlay(this.canvasLayer);
                },
            },
            {
                key: 'draw',
                value: function draw() {
                    self.canvasLayer.draw();
                },
            },
        ]);
        return Layer;
    })(BaseLayer);

    /**
     * @author kyle / http://nikai.us/
     */

    var geojson = {
        getDataSet: function getDataSet(geoJson) {
            var data = [];
            var features = geoJson.features;
            for (var i = 0; i < features.length; i++) {
                var feature = features[i];
                var geometry = feature.geometry;
                var properties = feature.properties;
                var item = {};
                for (var key in properties) {
                    item[key] = properties[key];
                }
                item.geometry = geometry;
                data.push(item);
            }
            return new DataSet(data);
        },
    };

    /**
     * @author kyle / http://nikai.us/
     */

    var csv = {
        CSVToArray: function CSVToArray(strData, strDelimiter) {
            // Check to see if the delimiter is defined. If not,
            // then default to comma.
            strDelimiter = strDelimiter || ',';

            // Create a regular expression to parse the CSV values.
            var objPattern = new RegExp(
                // Delimiters.
                '(\\' +
                    strDelimiter +
                    '|\\r?\\n|\\r|^)' +
                    // Quoted fields.
                    '(?:"([^"]*(?:""[^"]*)*)"|' +
                    // Standard fields.
                    '([^"\\' +
                    strDelimiter +
                    '\\r\\n]*))',
                'gi'
            );

            // Create an array to hold our data. Give the array
            // a default empty first row.
            var arrData = [[]];

            // Create an array to hold our individual pattern
            // matching groups.
            var arrMatches = null;

            // Keep looping over the regular expression matches
            // until we can no longer find a match.
            while ((arrMatches = objPattern.exec(strData))) {
                // Get the delimiter that was found.
                var strMatchedDelimiter = arrMatches[1];

                // Check to see if the given delimiter has a length
                // (is not the start of string) and if it matches
                // field delimiter. If id does not, then we know
                // that this delimiter is a row delimiter.
                if (strMatchedDelimiter.length && strMatchedDelimiter !== strDelimiter) {
                    // Since we have reached a new row of data,
                    // add an empty row to our data array.
                    arrData.push([]);
                }

                var strMatchedValue;

                // Now that we have our delimiter out of the way,
                // let's check to see which kind of value we
                // captured (quoted or unquoted).
                if (arrMatches[2]) {
                    // We found a quoted value. When we capture
                    // this value, unescape any double quotes.
                    strMatchedValue = arrMatches[2].replace(new RegExp('""', 'g'), '"');
                } else {
                    // We found a non-quoted value.
                    strMatchedValue = arrMatches[3];
                }

                // Now that we have our value string, let's add
                // it to the data array.
                arrData[arrData.length - 1].push(strMatchedValue);
            }

            // Return the parsed data.
            return arrData;
        },

        getDataSet: function getDataSet(csvStr) {
            var arr = this.CSVToArray(csvStr, ',');

            var data = [];

            var header = arr[0];

            for (var i = 1; i < arr.length - 1; i++) {
                var line = arr[i];
                var item = {};
                for (var j = 0; j < line.length; j++) {
                    var value = line[j];
                    if (header[j] == 'geometry') {
                        value = JSON.parse(value);
                    }
                    item[header[j]] = value;
                }
                data.push(item);
            }

            return new DataSet(data);
        },
    };

    exports.version = version;
    exports.canvasClear = clear;
    exports.canvasResolutionScale = resolutionScale$1;
    exports.canvasDrawSimple = drawSimple;
    exports.canvasDrawHeatmap = drawHeatmap;
    exports.canvasDrawGrid = drawGrid;
    exports.canvasDrawHoneycomb = drawHoneycomb;
    exports.webglDrawSimple = webglDrawSimple;
    exports.webglDrawPoint = point;
    exports.webglDrawLine = line;
    exports.webglDrawPolygon = polygon;
    exports.utilCityCenter = cityCenter;
    exports.utilCurve = curve;
    exports.utilForceEdgeBundling = ForceEdgeBundling;
    exports.utilDataRangeIntensity = Intensity;
    exports.utilDataRangeCategory = Category;
    exports.utilDataRangeChoropleth = Choropleth;
    exports.Map = MapHelper;
    exports.baiduMapCanvasLayer = CanvasLayer;
    exports.baiduMapAnimationLayer = AnimationLayer;
    exports.baiduMapLayer = Layer;
    exports.googleMapCanvasLayer = CanvasLayer$2;
    exports.googleMapLayer = Layer$2;
    exports.DataSet = DataSet;
    exports.geojson = geojson;
    exports.csv = csv;

    Object.defineProperty(exports, '__esModule', {
        value: true,
    });
});

    
截图如下