<!DOCTYPE html>
<!--
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>
        <!-- <script src="ut/lib/canteen.js"></script> -->
        <link rel="stylesheet" href="lib/reset.css" />
    </head>
    <body>
        <style>
        </style>



        <div id="main0"></div>






        <script>
        require([
            'echarts'
        ], function (echarts) {
            var option;

            var data = [];
            var dataCount = 1000;
            var startTime =  new Date();
            var categories = ['categoryA', 'categoryB', 'categoryC'];
            var types = [
                {name: 'JS Heap', color: '#7b9ce1'},
                {name: 'Documents', color: '#bd6d6c'},
                {name: 'Nodes', color: '#75d874'},
                {name: 'Listeners', color: '#e0bc78'},
                {name: 'GPU Memory', color: '#dc77dc'},
                {name: 'GPU', color: '#72b362'}
            ];

            // Generate mock data
            categories.forEach(function (category, index) {
                let start = 0;
                for (var i = 0; i < dataCount; i++) {
                    var typeItem = types[Math.round(Math.random() * (types.length - 1))];
                    data.push({
                        name: typeItem.name,
                        value: [
                            index,
                            i +  start,
                            i + 1 + start,
                            1
                        ],
                        itemStyle: {
                            color: typeItem.color
                        }
                    });
                    start
                }
            });

            function renderItem(params, api) {
                var categoryIndex = api.value(0);
                var start = api.coord([api.value(1), categoryIndex]);
                var end = api.coord([api.value(2), categoryIndex]);
                var height = api.size([0, 1])[1] * 0.6;

                var rectShape = echarts.graphic.clipRectByRect({
                    x: start[0],
                    y: start[1] - height / 2,
                    width: end[0] - start[0],
                    height: height
                }, {
                    x: params.coordSys.x,
                    y: params.coordSys.y,
                    width: params.coordSys.width,
                    height: params.coordSys.height
                });

                return rectShape && {
                    type: 'rect',
                    transition: ['shape'],
                    shape: rectShape,
                    style: api.style()
                };
            }

            option = {
                tooltip: {
                    formatter: function (params) {
                        return params.marker + params.name + ': ' + params.value[3] + ' ms';
                    }
                },
                title: {
                    text: 'Profile',
                    left: 'center'
                },
                dataZoom: [{
                    type: 'slider',
                    filterMode: 'weakFilter',
                    showDataShadow: false,
                    top: 400,
                    labelFormatter: ''
                }, {
                    type: 'inside',
                    filterMode: 'weakFilter'
                }],
                grid: {
                    height: 300
                },
                xAxis: {
                    min: 0,
                    scale: true,
                    axisLabel: {
                        formatter: function (val) {
                            return val + ' ms';
                        }
                    }
                },
                yAxis: {
                    data: categories
                },
                series: [{
                    type: 'custom',
                    renderItem: renderItem,
                    itemStyle: {
                        opacity: 0.8
                    },
                    encode: {
                        x: [1, 2],
                        y: 0
                    },
                    data: data
                }]
            };

            var chart = testHelper.create(echarts, 'main0', {
                title: [
                    'Test Case from https://github.com/apache/echarts/issues/14573',
                    'Should switch between progressive normally.'
                ],
                option: option,
                buttons: [{
                    text: 'Zoom in',
                    onclick: function () {
                        chart.dispatchAction({
                            type: 'dataZoom',
                            start: 10,
                            end: 12
                        });
                    }
                }, {
                    text: 'Zoom out',
                    onclick: function () {
                        chart.dispatchAction({
                            type: 'dataZoom',
                            start: 0,
                            end: 100
                        });
                    }
                }],
            });
        });
        </script>


    </body>
</html>

