
<!--
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>
        <script src="lib/jquery.min.js"></script>
        <script src="lib/dat.gui.min.js"></script>
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
            }
        </style>
        <div id="main"></div>
        <script>

            require([
                'echarts',

                'extension/dataTool',

                // 'echarts/chart/graph',

                // 'echarts/component/title',
                // 'echarts/component/legend',
                // 'echarts/component/geo',
                // 'echarts/component/tooltip',
                // 'echarts/component/visualMap',

                'theme/vintage'
            ], function (echarts, dataTool) {
                var gexf = dataTool.gexf;
                var chart = echarts.init(document.getElementById('main'), 'vintage', {

                });

                $.get('./data/les-miserables.gexf', function (xml) {
                    var graph = gexf.parse(xml);
                    var categories = [];
                    for (var i = 0; i < 9; i++) {
                        categories[i] = {
                            name: '类目' + i
                        };
                    }
                    graph.nodes.forEach(function (node) {
                        delete node.itemStyle;
                        node.value = node.symbolSize;
                        node.label = {
                            normal: {
                                show: node.symbolSize > 30
                            },
                            emphasis: {
                                show: true
                            }
                        };
                        node.category = node.attributes['modularity_class'];
                    });
                    graph.links.forEach(function (link) {
                        delete link.lineStyle;
                    });
                    var option = {
                        aria: {
                            show: true,
                            description: 'Les Miserables 的关系主要分为六个区域，这张图描述了他们之间的相互关联。'
                        },
                        tooltip: {},
                        legend: [{
                            // selectedMode: 'single',
                            data: categories.map(function (a) {
                                return a.name;
                            })
                        }],
                        animationDurationUpdate: 1500,
                        animationEasingUpdate: 'quinticInOut',
                        series : [
                            {
                                name: 'Les Miserables',
                                type: 'graph',
                                layout: 'none',
                                data: graph.nodes,
                                links: graph.links,
                                categories: categories,
                                cursor: 'crosshair',
                                roam: true,
                                draggable: true,
                                itemStyle: {
                                    normal: {
                                        borderColor: '#fff',
                                        borderWidth: 2,
                                        shadowBlur: 10,
                                        shadowColor: 'rgba(0, 0, 0, 0.3)'
                                    }
                                },
                                emphasis: {
                                    focus: 'adjacency'
                                },
                                // edgeSymbol: ['none', 'arrow'],
                                // scaleLimit: {
                                //     min: 1.5,
                                //     max: 2
                                // },
                                label: {
                                    normal: {
                                        position: 'right',
                                        formatter: '{b}'
                                    }
                                },
                                lineStyle: {
                                    normal: {
                                        color: 'source',
                                        curveness: 0.3
                                    },
                                    emphasis: {
                                        width: 10
                                    }
                                }
                            }
                        ]
                    };

                    chart.setOption(option);

                    var config = {
                        layout: 'none',
                        focusNodeAdjacency: true,
                        manualFocusNodeAdjacency: function () {
                            chart.dispatchAction({
                                type: 'highlight',
                                seriesName: 'Les Miserables',
                                dataIndex: 2
                            });
                        },
                        manualUnfocusNodeAdjacency: function () {
                            chart.dispatchAction({
                                type: 'downplay',
                                seriesName: 'Les Miserables'
                            });
                        },
                        'circular.rotateLabel': false
                    };

                    chart.on('click', function (params) {
                        console.log(params, params.data);
                    });

                    var gui = new dat.GUI();
                    gui.add(config, 'layout', ['none', 'circular'])
                        .onChange(function (value) {
                            chart.setOption({
                                series: [{
                                    name: 'Les Miserables',
                                    layout: value
                                }]
                            });
                        });
                    gui.add(config, 'focusNodeAdjacency')
                        .onChange(function (value) {
                            chart.setOption({
                                series: [{
                                    name: 'Les Miserables',
                                    emphasis: {
                                        focus: config.focusNodeAdjacency ? 'adjacency' : null
                                    }
                                }]
                            });
                        });
                    gui.add(config, 'manualFocusNodeAdjacency');
                    gui.add(config, 'manualUnfocusNodeAdjacency');
                    gui.add(config, 'circular.rotateLabel')
                        .onChange(function (value) {
                            chart.setOption({
                                series: [{
                                    name: 'Les Miserables',
                                    circular: {rotateLabel: !!value}
                                }]
                            });
                        });
                });
            });
        </script>
    </body>
</html>