
<!--
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>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
            }
        </style>
        <div id="main"></div>
        <script>

            require([
                'echarts'
                // 'echarts/chart/bar',
                // 'echarts/chart/line',
                // 'echarts/component/legend',
                // 'echarts/component/grid',
                // 'echarts/component/dataZoom',
                // 'echarts/component/tooltip'
            ], function (echarts) {
                var myChart;
                var lineCount = 1;
                var pointCount = 60 * 10000;

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

                var option = {
                    tooltip : {
                        trigger: 'axis',
                        // showContent: false,
                        axisPointer: {
                            type: 'cross'
                            // animation: false
                        }
                    },
                    legend: {
                        data:[]
                    },
                    // dataZoom: [{
                    //     show: true,
                    //     realtime: true,
                    //     // showDataShadow: false,
                    //     start: 50,
                    //     end: 60
                    // }],
                    xAxis : [
                        {
                            type : 'time'
                        }
                    ],
                    yAxis : [
                        {
                            type : 'value'
                        }
                    ],
                    series: [],
                    animation: false
                };

                var lineStyle = {
                    normal: {
                        width: 2,
                        opacity: 1
                    }
                };

                var date = [];
                var oneDay = 24 * 3600 * 1000;
                var base = +new Date(1897, 9, 3);
                for (var j = 0; j < pointCount; j++) {
                    var now = new Date(base += oneDay);
                    date.push([now.getFullYear(), now.getMonth() + 1, now.getDate()].join('-'));
                }
                for (var i = 0; i < lineCount; i++) {
                    var y = Math.random() * 1000;
                    var values = [];
                    for (var j = 0; j < pointCount; j++) {
                        y += Math.round(10 + Math.random() * (-10 - 10));
                        values.push(
                            [
                                date[j],
                                // Math.random() < 0.1 ? '-' : y
                                y
                            ]
                        );
                    }

                  option.legend.data.push( 'line' + i );
                  option.series.push({
                    name: 'line' + i,
                    type: 'line',
                    sampling: 'average',
showAllSymbol: true,
symbol: 'emptyCircle',
// symbolSize: 0.1,
                    hoverAnimation: false,
                    // showSymbol: false,
                    data: values,
                    lineStyle: lineStyle
                  });
                }

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