
<!--
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/esl.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];

        var dataURL = './data/flight.json';

        require([
            'echarts'

            // 'echarts/chart/lines',
            // 'echarts/component/legend',
            // 'extension/bmap'
        ], function (echarts) {

            $.get('./data/map/json/world.json', function (worldJson) {
                echarts.registerMap('world', worldJson);

                $.get(dataURL, function (data) {
                    var config = {
                        dataLoading: 'whole',
                        streamThreshold: 0,
                        streamRender: true,
                        largeModel: true
                    };

                    var chart;
                    var infoEl = document.getElementById('info');

                    init();

                    function init() {
                        if (chart) {
                            chart.dispose();
                        }

                        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>