<!DOCTYPE html>
<!--
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">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src="lib/esl.js"></script>
        <script src="lib/config.js"></script>
        <script src="lib/jquery.min.js"></script>
        <script src="lib/facePrint.js"></script>
        <script src="lib/testHelper.js"></script>
        <link rel="stylesheet" href="lib/reset.css">
    </head>
    <body>
        <style>
            .test-title {
                background: #146402;
                color: #fff;
            }
        </style>


        <div id="main0"></div>


        <script>

            var chart;

            require([
                'echarts'/*, 'map/js/china' */
            ], function (echarts) {


                var provinces = ['shanghai', 'hebei','shanxi','neimenggu','liaoning','jilin','heilongjiang','jiangsu','zhejiang','anhui','fujian','jiangxi','shandong','henan','hubei','hunan','guangdong','guangxi','hainan','sichuan','guizhou','yunnan','xizang','shanxi1','gansu','qinghai','ningxia','xinjiang', 'beijing', 'tianjin', 'chongqing', 'xianggang', 'aomen'];
                var provincesText = ['上海', '河北', '山西', '内蒙古', '辽宁', '吉林','黑龙江',  '江苏', '浙江', '安徽', '福建', '江西', '山东','河南', '湖北', '湖南', '广东', '广西', '海南', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆', '北京', '天津', '重庆', '香港', '澳门'];

                function showProvince() {
                    var name = provinces[currentIdx];

                    // myChart.showLoading();

                    $.get('./data/map/json/province/' + name + '.json', function (geoJson) {

                        // myChart.hideLoading();

                        echarts.registerMap(name, geoJson);

                        chart.setOption({
                            backgroundColor: '#404a59',
                            title: {
                                text: provincesText[currentIdx],
                                left: 'center',
                                textStyle: {
                                    color: '#fff'
                                }
                            },
                            series: [
                                {
                                    type: 'map',
                                    mapType: name,
                                    label: {
                                        emphasis: {
                                            textStyle: {
                                                color: '#fff'
                                            }
                                        }
                                    },
                                    itemStyle: {
                                        normal: {
                                            borderColor: '#389BB7',
                                            areaColor: '#fff',
                                        },
                                        emphasis: {
                                            areaColor: '#389BB7',
                                            borderWidth: 0
                                        }
                                    },
                                    animation: false
                                    // animationDurationUpdate: 1000,
                                    // animationEasingUpdate: 'quinticInOut'
                                }
                            ]
                        });

                    });
                }

                var currentIdx = 0;

                var option = {
                    graphic: [{
                        id: 'left-btn',
                        type: 'circle',
                        shape: { r: 20 },
                        style: {
                            text: '<',
                            fill: '#eee'
                        },
                        left: 10,
                        top: 'middle',
                        onclick: function () {
                            currentIdx -= 1;
                            if (currentIdx < 0) {
                                currentIdx += provinces.length;
                            }
                            showProvince();
                        }
                    }, {
                        id: 'right-btn',
                        type: 'circle',
                        shape: { r: 20 },
                        style: {
                            text: '>',
                            fill: '#eee'
                        },
                        top: 'middle',
                        right: 10,
                        onclick: function () {
                            currentIdx = (currentIdx + 1) % provinces.length;
                            showProvince();
                        }
                    }],

                    series: []
                };

                chart = testHelper.create(echarts, 'main0', {
                    option: option
                });

                showProvince();



            });

        </script>
    </body>
</html>