
<!--
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>
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
            }
            #chart1, #chart2 {
                width: 50%;
                height: 100%;
                float: left;
            }
        </style>
        <div id="main">
            <div id="chart1"></div>
            <div id="chart2"></div>
        </div>
        <script>


            require([
                'echarts'
                // 'echarts/chart/scatter',
                // 'echarts/component/legend',
                // 'echarts/component/grid',
                // 'echarts/component/visualMap',
                // 'echarts/component/tooltip'
            ], function (echarts) {

                var chart1 = echarts.init(document.getElementById('chart1'));
                var chart2 = echarts.init(document.getElementById('chart2'));

                var data1 = [];

                var symbolCount = 6;

                for (var i = 0; i < 100; i++) {
                    data1.push([
                        Math.random() * 5,
                        Math.random() * 4,
                        Math.random() * 20,
                        Math.round(Math.random() * (symbolCount - 1))
                    ]);
                }

                chart1.setOption({
                    legend: {
                        top: 50,
                        data: ['scatter']
                    },
                    tooltip: {
                        formatter: '{c}'
                    },
                    grid: {
                        top: '26%',
                        bottom: '26%'
                    },
                    xAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    yAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    visualMap: [
                        {
                            realtime: false,
                            left: 'right',
                            // selectedMode: 'single',
                            selectedMode: 'multiple',
                            backgroundColor: '#eee',
                            dimension: 2,
                            selected: [],
                            min: 0,
                            max: 24,
                            precision: 0,
                            splitNumber: 0,
                            calculable: true,
                            inRange: { // visual for short cut
                                color: ['#006edd', '#e0ffff']
                            }
                        }
                    ],
                    series: [
                        {
                            name: 'scatter',
                            type: 'scatter',
                            symbolSize: 30,
                            data: data1
                        }
                    ]
                });

                chart2.setOption({
                    legend: {
                        top: 50,
                        data: ['scatter']
                    },
                    tooltip: {
                        formatter: '{c}'
                    },
                    grid: {
                        top: '26%',
                        bottom: '26%'
                    },
                    xAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    yAxis: {
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    },
                    visualMap: [
                        {
                            left: 'right',
                            // selectedMode: 'single',
                            selectedMode: 'multiple',
                            backgroundColor: '#eee',
                            dimension: 2,
                            selected: [],
                            min: 0,
                            max: 24,
                            precision: 0,
                            splitNumber: 0,
                            calculable: true,
                            inRange: { // visual for short cut
                                color: ['#006edd', '#e0ffff']
                            }
                        }
                    ],
                    series: [
                        {
                            name: 'scatter',
                            type: 'scatter',
                            symbolSize: 30,
                            data: data1
                        }
                    ]
                });

                echarts.connect([chart1, chart2]);

                // bindAction(chart1, chart2);
                // bindAction(chart2, chart1);

                // function bindAction(fromChart, toChart) {
                //     fromChart.on('legendselectchanged', function (params) {
                //         toChart.dispatchAction({type: 'legendToggleSelect', name: params.name}, true);
                //     });
                //     fromChart.on('highlight', function (params) {
                //         toChart.dispatchAction({type: 'highlight', seriesName: params.seriesName}, true);
                //     });
                //     fromChart.on('downplay', function (params) {
                //         toChart.dispatchAction({type: 'downplay', seriesName: params.seriesName}, true);
                //     });
                // }


            });

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