
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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.
-->

<html>
    <head>
        <meta charset='utf-8'>
        <script src='lib/simpleRequire.js'></script>
        <script src='lib/config.js'></script>
        <script src='lib/jquery.min.js'></script>
        <script src="lib/dat.gui.min.js"></script>
        <meta name='viewport' content='width=device-width, initial-scale=1' />
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
            }
            #info {
                position: fixed;
                left: 5;
                top: 5;
                height: 100px;
                width: 200px;
                background: #fff;
                border: 2px solid #999;
                z-index: 9999;
            }
        </style>
        <div id="info">Rendering (large: false), please wait ...</div>
        <div id='main'></div>
        <script>

        var xs = [440000, 450000];
        var ys = [4368000, 4537000];

        require([
            'echarts',
            './data/map/json/world.json',
            './data/flight.json'
        ], function (echarts, worldJson, data) {

            echarts.registerMap('world', worldJson);

            var config = {
                dataLoading: 'whole',
                streamThreshold: 0,
                streamRender: true,
                largeModel: true
            };

            var infoEl = document.getElementById('info');
            if (chart) {
                chart.dispose();
            }

            var chart = echarts.init(document.getElementById('main'));

            function getAirportCoord(idx) {
                return [data.airports[idx][3], data.airports[idx][4]];
            }
            var routes = data.routes.map(function (airline) {
                return [
                    getAirportCoord(airline[1]),
                    getAirportCoord(airline[2])
                ];
            });

            var option = {
                streamStep: 4000,
                title: {
                    text: 'World Flights',
                    left: 'center',
                    textStyle: {
                        color: '#eee'
                    }
                },
                backgroundColor: '#003',
                tooltip: {
                    formatter: function (param) {
                        var route = data.routes[param.dataIndex];
                        return data.airports[route[1]][1] + ' > ' + data.airports[route[2]][1];
                    }
                },
                geo: {
                    map: 'world',
                    left: 0,
                    right: 0,
                    roam: true,
                    silent: true,
                    itemStyle: {
                        normal: {
                            borderColor: '#003',
                            color: '#005'
                        }
                    }
                },
                series: [{
                    type: 'lines',
                    coordinateSystem: 'geo',
                    blendModel: 'lighter',
                    data: routes,
                    // Test not large mode.
                    large: false,
                    largeThreshold: 100,
                    lineStyle: {
                        normal: {
                            opacity: 0.05,
                            width: 0.5,
                            curveness: 0.3
                        }
                    },
                    // 设置混合模式为叠加
                    blendMode: 'lighter'
                }]
            };

            chart.on('finished', function () {
                infoEl.innerHTML = 'Finished (large: false). Please test roam (in not large mode, should no error thrown)';
            });

            chart.setOption(option);
        });
        </script>
    </body>
</html>