<!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>
        <div id="main1"></div>




        <script>
        var shapesMade;
        var WeirdTriangle;
        var Rect2;

        function makeShapes(echarts) {
            if (shapesMade) {
                return;
            }
            shapesMade = true;

            WeirdTriangle = echarts.graphic.extendShape({
                type: 'anyway',

                shape: {
                    a: 0,
                    b: 100,
                    c: 200
                },

                buildPath: function (ctx, shape) {
                    ctx.moveTo(shape.a, shape.b);
                    ctx.lineTo(shape.b, shape.c);
                    ctx.lineTo(shape.c, shape.a);
                    ctx.closePath();
                }
            });

            Rect2 = echarts.graphic.extendShape({
                type: 'anyway2',

                shape: {
                    x: 0,
                    y: 0,
                    width: 0,
                    height: 0
                },

                buildPath: function (ctx, shape) {
                    ctx.moveTo(shape.x, shape.y);
                    ctx.lineTo(shape.x + shape.width, shape.y);
                    ctx.lineTo(shape.x, shape.y + shape.height);
                    ctx.lineTo(shape.x + shape.width, shape.y + shape.height);
                    ctx.closePath();
                }
            });

            echarts.graphic.registerShape('weirdTriangle', WeirdTriangle);
            echarts.graphic.registerShape('rect', Rect2); // Overwrite rect.
            echarts.graphic.registerShape('group', WeirdTriangle); // Should not make sense.

            var MyWeirdGot = echarts.graphic.getShapeClass('weirdTriangle');
            if (MyWeirdGot !== WeirdTriangle) {
                throw new Error('echarts.getShapeClass error');
            }
        }
        </script>




        <script>
        require(['echarts'/*, 'map/js/china' */], function (echarts) {
            makeShapes(echarts);
            var option;

            option = {
                xAxis: {},
                yAxis: {},
                series: {
                    type: 'custom',
                    renderItem: function (params, api) {
                        return {
                            type: 'group',
                            children: [{
                                type: 'weirdTriangle',
                                shape: {
                                    a: api.value(0),
                                    b: api.value(1),
                                    c: api.value(2)
                                },
                                style: {
                                    fill: 'red',
                                    stroke: 'green',
                                    lineWidth: 2
                                }
                            }, {
                                type: 'rect',
                                shape: {
                                    x: api.value(3),
                                    y: api.value(4),
                                    width: api.value(5),
                                    height: api.value(6)
                                },
                                style: {
                                    fill: 'red',
                                    stroke: 'green',
                                    lineWidth: 2
                                }
                            }]
                        }
                    },
                    data: [
                        [55, 66, 77, 388, 99, 101, 111],
                        [111, 222, 333, 500, 200, 50, 100]
                    ]
                }
            };

            var chart = testHelper.create(echarts, 'main0', {
                title: [
                    'Custom shape in custom series.',
                    'Two triangles should be displayed (fill: red, stroke: green)',
                    'Two sandglass should be displayed (fill: red, stroke: green)'
                ],
                option: option
                // height: 300,
                // buttons: [{text: 'btn-txt', onclick: function () {}}],
                // recordCanvas: true,
            });
        });
        </script>






        <script>
        require(['echarts'/*, 'map/js/china' */], function (echarts) {
            makeShapes(echarts);
            var option;

            option = {
                graphic: {
                    type: 'group',
                    children: [{
                        type: 'weirdTriangle',
                        shape: {
                            a: 111,
                            b: 222,
                            c: 333
                        },
                        style: {
                            fill: 'red',
                            stroke: 'green',
                            lineWidth: 2
                        }
                    }, {
                        type: 'rect',
                        shape: {
                            x: 500,
                            y: 200,
                            width: 50,
                            height: 100
                        },
                        style: {
                            fill: 'red',
                            stroke: 'green',
                            lineWidth: 2
                        }
                    }]
                }
            };

            var chart = testHelper.create(echarts, 'main1', {
                title: [
                    'Custom shape in graphic component.',
                    'One triangles should be displayed (fill: red, stroke: green)',
                    'One sandglass should be displayed (fill: red, stroke: green)'
                ],
                option: option
                // height: 300,
                // buttons: [{text: 'btn-txt', onclick: function () {}}],
                // recordCanvas: true,
            });
        });
        </script>




    </body>
</html>

