
<!--
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>
        <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'
            ], 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>