
<!--
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" />
        <link rel="stylesheet" href="lib/reset.css">
    </head>
    <body>
        <style>
            .chart {
                width: 100%;
                height: 300px;
            }
            h2 {
                text-align: center;
                font-size: 16px;
                line-height: 30px;
                font-weight: normal;
                color: #eee;
                background: #333;
            }
        </style>

        <h2>value axis | series.data: [[x, y], [x, y], ...]</h2>
        <div class="chart" id="main0"></div>

        <h2>value axis | series.data: [x, x, ...]</h2>
        <div class="chart" id="main1"></div>

        <h2>category axis | series.data: [y, y, ...]</h2>
        <div class="chart" id="main2"></div>



        <script>

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

                var main = document.getElementById('main0');
                if (!main) {
                    return;
                }
                var chart = echarts.init(main);

                var data1 = [];

                var random = function (max) {
                    return (Math.random() * max).toFixed(3);
                };

                for (var i = 0; i < 50; i++) {
                    data1.push([random(5), random(2)]);
                }

                chart.setOption({
                    animation: false,
                    tooltip: {
                        trigger: 'axis'
                    },
                    legend: {
                        data: ['scatter']
                    },
                    // toolbox: {
                    //     feature: {
                    //         dataZoom: {show: true},
                    //         restore: {show: true}
                    //     }
                    // },
                    singleAxis: {
                        bottom: '15%'
                    },
                    dataZoom: [{
                        type: 'inside'
                    }, {
                        type: 'slider',
                        height: 20,
                        bottom: 5
                    }],
                    series: [{
                        name: 'scatter',
                        type: 'scatter',
                        coordinateSystem: 'singleAxis',
                        symbolSize: function (val) {
                            return val[1] * 40;
                        },
                        data: data1
                    }],
                    animationDelay: function (idx) {
                        return idx * 20;
                    },
                    animationDelayUpdate: function (idx) {
                        return idx * 20;
                    }
                });
            });

        </script>







        <script>

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

                var main = document.getElementById('main1');
                if (!main) {
                    return;
                }
                var chart = echarts.init(main);

                var data1 = [];

                var random = function (max) {
                    return (Math.random() * max).toFixed(3);
                };

                for (var i = 0; i < 50; i++) {
                    data1.push(random(5));
                }

                chart.setOption({
                    tooltip: {
                        trigger: 'axis'
                    },
                    legend: {
                        data: ['scatter']
                    },
                    singleAxis: {
                        bottom: '15%'
                    },
                    dataZoom: [{
                        type: 'inside'
                    }, {
                        type: 'slider',
                        height: 20,
                        bottom: 5
                    }],
                    series: [{
                        name: 'scatter',
                        type: 'scatter',
                        coordinateSystem: 'singleAxis',
                        symbolSize: 20,
                        data: data1
                    }]
                });
            });

        </script>







        <script>

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

                var main = document.getElementById('main2');
                if (!main) {
                    return;
                }
                var chart = echarts.init(main);

                var data1 = [];

                var random = function (max) {
                    return (Math.random() * max).toFixed(3);
                };

                for (var i = 0; i < 3; i++) {
                    data1.push(random(5));
                }

                chart.setOption({
                    tooltip: {
                        trigger: 'axis'
                    },
                    legend: {
                        data: ['scatter']
                    },
                    singleAxis: {
                        type: 'category',
                        data: ['类目1', '类目2', '类目3', '类目4', '类目5'],
                        bottom: '15%'
                    },
                    dataZoom: [{
                        type: 'inside'
                    }, {
                        type: 'slider',
                        height: 20,
                        bottom: 5
                    }],
                    series: [{
                        name: 'scatter',
                        type: 'scatter',
                        coordinateSystem: 'singleAxis',
                        symbolSize: 20,
                        symbolSize: function (val) {
                            return val * 40;
                        },
                        data: data1
                    }]
                });
            });

        </script>



    </body>
</html>