
<!--
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/simpleRequire.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>

        <div id="main0" class="chart"></div>
        <div id="main1" class="chart"></div>




        <script>

            require(['echarts'], function (echarts) {

                var data1 = [[new Date(1498258800000), 10], [new Date(1498345200000), 15], [new Date(1498431600000), 15], [new Date(1498518000000), 15]];
                var data2 = [[new Date(1498258800000), 15], [new Date(1498345200000), 20], [new Date(1498431600000), 15], [new Date(1498518000000), 15]];
                var data3 = [[new Date(1498258800000), 20], [new Date(1498345200000), 10], [new Date(1498431600000), 15], [new Date(1498518000000), 15]];

                var itemStyle = {
                    normal: {
                        barBorderRadius: 5,
                        label: {
                            show: true,
                            position: 'outside'
                        }
                    },
                    emphasis: {
                        label: {
                            position: 'outside'
                        },
                        barBorderColor: '#fff',
                        barBorderWidth: 1,
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        shadowColor: 'rgba(0,0,0,0.5)'
                    }
                };

                var option = {
                    backgroundColor: '#eee',
                    legend: {
                    },
                    xAxis: {
                        type: 'time',
                        axisLabel: {
                            formatter: function (val) {
                                return echarts.format.formatTime('yyyy-MM-dd\nhh:ss:mm.SSS', val);
                            }
                        }
                    },
                    yAxis: {
                        // axisLabel: {
                        //     show: false
                        // },
                        axisTick: {
                            show: false
                        },
                        splitArea: {
                            show: false
                        }
                    },
                    grid: {
                        bottom: 80
                    },
                    dataZoom: [{
                        type: 'slider',
                        labelFormatter: function (val) {
                            return echarts.format.formatTime('yyyy-MM-dd\nhh:ss:mm.SSS', val);
                        }
                    }, {
                        type: 'inside'
                    }],
                    series: [{
                        name: 'bar',
                        type: 'bar',
                        data: data1
                    }, {
                        name: 'bar2',
                        type: 'bar',
                        data: data2
                    }, {
                        name: 'bar3',
                        type: 'bar',
                        data: data3
                    }]
                };

                testHelper.create(echarts, 'main0', {
                    title: 'time axis',
                    option: option
                });

            });

        </script>









        <script type="text/javascript">
            require(['echarts'], function (echarts) {

                var data0 = [];

                var MAX_DIM1 = 100;

                var itemStyle = {
                    normal: {
                        opacity: 0.8,
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.3)'
                    }
                };

                var last = 60;
                var lastDelta = 20;
                for (var i = 0; i < MAX_DIM1; i++) {
                    lastDelta += (Math.random() - 0.5) * 15;
                    data0.push([
                        i,
                        last += lastDelta
                    ]);
                }

                var option = {
                    grid: {
                        top: 100,
                        bottom: 100
                    },
                    xAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    yAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    visualMap: [
                        {
                            show: true,
                            left: 'center',
                            bottom: 20,
                            orient: 'horizontal',
                            itemWidth: 20,
                            itemHeight: 200,
                            min: 0,
                            max: MAX_DIM1,
                            calculable: true,
                            range: [5, 95],
                            dimension: 0,
                            inRange: {
                                colorHue: [0, 300],
                                colorLightness: 0.35,
                                colorSaturation: 1
                            },
                            outOfRange: {
                                color: '#eee'
                            }
                        }
                    ],
                    series: [
                        {
                            name: 'bar',
                            type: 'bar',
                            barMaxWidth: 10,
                            itemStyle: itemStyle,
                            data: data0
                        }
                    ]
                };

                testHelper.create(echarts, 'main1', {
                    title: 'value axis',
                    option: option
                });
            })
        </script>







    </body>
</html>