
<!--
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">
        <title>calendar</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" href="lib/reset.css">
        <script src="lib/esl.js"></script>
        <script src="lib/config.js"></script>
        <script src="lib/jquery.min.js"></script>
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
            }
        </style>
        <div id="main"></div>
        <script>


            var getVirtulData =  function(year) {

                year = year || '2017';

                var datas = [];

                var arr31 = [1, 3, 5, 7, 8, 10, 12];
                var arr30 = [4, 6, 9, 11];
                for (var i = 1; i <= 31; i++) {
                    for (var j = arr31.length - 1; j >= 0; j--) {
                        datas.push([year + '-' + arr31[j] + '-' + i, Math.floor(Math.random() * 1000)]);
                    }
                }
                for (var i = 1; i <= 30; i++) {
                    for (var j = arr30.length - 1; j >= 0; j--) {
                        datas.push([year + '-' + arr30[j] + '-' + i, Math.floor(Math.random() * 1000)]);
                    }
                }
                for (var i = 1; i <= 29; i++) {
                    datas.push([year + '-2-' + i, Math.floor(Math.random() * 1000)]);
                }
                return datas;
            }

            var graphData = getVirtulData(2017);

            graphData = [
                [
                    1485878400000,
                    260
                ],
                [
                    1486137600000,
                    200
                ],
                [
                    1486569600000,
                    279
                ],
                [
                    1486915200000,
                    847
                ],
                [
                    1487347200000,
                    241
                ],
                [
                    1487779200000,
                    411
                ],
                [
                    1488124800000,
                    985
                ]
            ];

            var links = graphData.map(function (item, idx) {
                return {
                    source: idx,
                    target: idx + 1
                };
            });
            links.pop();

            require([
                'echarts'
                // 'echarts/chart/heatmap',
                // 'echarts/chart/scatter',
                // 'echarts/chart/effectScatter',
                // 'echarts/chart/graph',
                // 'echarts/component/title',
                // 'echarts/component/legend',
                // 'echarts/component/calendar',
                // 'echarts/component/tooltip',
                // 'echarts/component/visualMap'
            ], function (echarts) {

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

                chart.setOption({
                    tooltip: {
                        position: 'top'
                    },

                    visualMap: {
                        min: 0,
                        max: 1000,
                        calculable: true,
                        seriesIndex: [1, 2, 3],
                        orient: 'horizontal',
                        left: 950,
                        top: 400
                    },

                    calendar: [
                    {
                        yearLabel: {
                            margin: 40
                        },
                        cellSize: 40,
                        range: '2017-02'
                    },
                    {
                        yearLabel: {
                            margin: 40
                        },
                        cellSize: 40,
                        left: 350,
                        range: '2017-01'
                    },
                    {
                        yearLabel: {
                            margin: 40
                        },
                        cellSize: 40,
                        left: 650,
                        range: '2017-03'
                    },
                    {
                        yearLabel: {
                            margin: 40
                        },
                        cellSize: 40,
                        left: 950,
                        range: '2017-04'
                    }],

                    series: [{
                        type: 'graph',
                        edgeSymbol: ['none', 'arrow'],
                        coordinateSystem: 'calendar',
                        links: links,
                        symbolSize: 10,
                        calendarIndex: 0,
                        data: graphData
                    }, {
                        type: 'effectScatter',
                        coordinateSystem: 'calendar',
                        calendarIndex: 1,
                        symbolSize: function (val) {
                            return val[1] / 40;
                        },
                        data: getVirtulData(2017)
                    }, {
                        type: 'scatter',
                        coordinateSystem: 'calendar',
                        calendarIndex: 2,
                        symbolSize: function (val) {
                            return val[1] / 60;
                        },
                        data: getVirtulData(2017)
                    }, {
                        type: 'heatmap',
                        coordinateSystem: 'calendar',
                        calendarIndex: 3,
                        data: getVirtulData(2017)
                    }]
                });

                $(window).resize(function() {
                    chart.resize();
                });
            });

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