| /* | 
 | * 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. | 
 | */ | 
 |  | 
 | import { createChart, getGraphicElements, getECModel } from '../../../core/utHelper'; | 
 | // import { imageURI } from './setOptionImageURI'; | 
 | import { EChartsType } from '../../../../../src/echarts'; | 
 | import Element from 'zrender/src/Element'; | 
 | import { EChartsOption } from '../../../../../src/export/option'; | 
 | import { | 
 |     GraphicComponentOption, | 
 |     GraphicComponentImageOption | 
 | } from '../../../../../src/component/graphic/GraphicModel'; | 
 | import Group from 'zrender/src/graphic/Group'; | 
 | import { Dictionary } from 'zrender/src/core/types'; | 
 |  | 
 |  | 
 |  | 
 | // eslint-disable-next-line max-len | 
 | const imageURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANwAAADcCAYAAAAbWs+BAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gIUARQAHY8+4wAAApBJREFUeNrt3cFqAjEUhlEjvv8rXzciiiBGk/He5JxdN2U649dY+KmnEwAAAAAv2uMXEeGOwERntwAEB4IDBAeCAwQHggPBAYIDwQGCA8GB4ADBgeAAwYHgAMGB4EBwgOCgpkuKq2it/r8Li2hbvGKqP6s/PycnHHv9YvSWEgQHCA4EBwgOBAeCAwQHggMEByXM+QRUE6D3suwuPafDn5MTDg50KXnVPSdxa54y/oYDwQGCA8EBggPBAYIDwYHggBE+X5rY3Y3Tey97Nn2eU+rnlGfaZa6Ft5SA4EBwgOBAcCA4QHAgOEBwIDjgZu60y1xrDPtIJxwgOBAcIDgQHAgOEBwIDhAcCA4EBwgOBAcIDgQHCA4EB4IDBAeCAwQHggPBAYIDwQGCA8GB4ADBgeAAwYHgAMGB4GADcz9y2McIgxMOBAeCAwQHggMEB4IDwQGCA8EBggPBATdP6+KIGPRdW7i1LCFi6ALfCQfeUoLgAMGB4ADBgeBAcIDgQHCA4CCdOVvK7quwveQgg7eRTjjwlhIQHAgOBAcIDgQHCA4EB4IDBAfl5dhSdl+17SX3F22rdLlOOBAcCA4QHAgOEBwIDgQHCA4EBwgO0qm5pez6Ce0uSym2jXTCgeAAwYHgQHCA4EBwgOBAcCA4QHBQ3vpbyu47Yns51OLbSCccCA4QHAgOBAcIDgQHCA4EB4ID5jDt+vkObjgFM9dywoHgAMGB4EBwgOBAcIDgQHAgOEBwsA5bysPveMLtpW2kEw4EBwgOBAcIDgQHggMEB4IDBAeCg33ZUqZ/Ql9sL20jnXCA4EBwIDhAcCA4QHAgOBAcIDgQHNOZai3DlhKccCA4QHAgOEBwIDgQHCA4AAAAAGA1VyxaWIohrgXFAAAAAElFTkSuQmCC'; | 
 |  | 
 | // function loadImage(onload: (img: HTMLImageElement) => void) { | 
 | //     const img = new window.Image(); | 
 | //     img.onload = function () { | 
 | //         onload(img); | 
 | //     }; | 
 | //     img.src = imageURI; | 
 | // } | 
 | // FIXME: TMEP use rect, would have used image. | 
 | // node-canvas will throw error when using data URI to zrender directly. | 
 | // Havn't dig it out why yet. | 
 | function tmpConvertImageOption(opt: GraphicComponentImageOption): object { | 
 |     const outOpt = opt as Dictionary<unknown>; | 
 |     outOpt.type = 'rect'; | 
 |     const style = opt.style || {}; | 
 |     delete style.image; | 
 |     outOpt.shape = { | 
 |         x: style.x || 0, | 
 |         y: style.y || 0, | 
 |         width: style.width || 0, | 
 |         height: style.height || 0 | 
 |     }; | 
 |     return outOpt; | 
 | } | 
 |  | 
 |  | 
 | describe('graphic_setOption', function () { | 
 |  | 
 |     const NUMBER_PRECISION = 6; | 
 |  | 
 |     function propHasAll(els: Element[], propsObjList: object[]) { | 
 |         for (let i = 0; i < propsObjList.length; i++) { | 
 |             propHas(els[i], propsObjList[i]); | 
 |         } | 
 |     } | 
 |  | 
 |     function propHas(target: object, propsObj: object): void { | 
 |         if (target == null || propsObj == null) { | 
 |             expect(false).toEqual(true); | 
 |         } | 
 |         expect(typeof target === 'object' && typeof propsObj === 'object').toEqual(true); | 
 |  | 
 |         // propsObj can be array | 
 |         if (propsObj instanceof Array) { | 
 |             expect(target instanceof Array).toEqual(true); | 
 |             for (let i = 0; i < propsObj.length; i++) { | 
 |                 each((target as Element[])[i], propsObj[i], i); | 
 |             } | 
 |         } | 
 |         else { | 
 |             for (const name in propsObj) { | 
 |                 if (propsObj.hasOwnProperty(name)) { | 
 |                     each((target as any)[name], (propsObj as any)[name], name); | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |         function each(targetVal: unknown, propVal: unknown, keyInfo: string | number): void { | 
 |             // console.log(targetVal, propVal, keyInfo); | 
 |             if (propVal == null) { | 
 |                 expect(targetVal == null).toEqual(true); | 
 |             } | 
 |             // object or array | 
 |             else if (typeof propVal === 'object') { | 
 |                 propHas(targetVal as object, propVal); | 
 |             } | 
 |             else if (typeof propVal === 'number') { | 
 |                 expect(typeof targetVal).toEqual('number'); | 
 |                 expect((targetVal as number).toFixed(NUMBER_PRECISION)).toEqual(propVal.toFixed(NUMBER_PRECISION)); | 
 |             } | 
 |             else { | 
 |                 expect(targetVal).toStrictEqual(propVal); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |  | 
 |     let chart: EChartsType; | 
 |     beforeEach(function () { | 
 |         chart = createChart(); | 
 |     }); | 
 |  | 
 |     afterEach(function () { | 
 |         chart.dispose(); | 
 |     }); | 
 |  | 
 |     describe('option', function () { | 
 |  | 
 |         it('optionFlatten', function () { | 
 |             chart.setOption({ | 
 |                 graphic: [ | 
 |                     tmpConvertImageOption({ | 
 |                         id: 'uriimg', | 
 |                         type: 'image', | 
 |                         name: 'nameuriimg', | 
 |                         originX: 20, | 
 |                         originY: 20, | 
 |                         left: 10, | 
 |                         top: 10, | 
 |                         style: { | 
 |                             image: imageURI, | 
 |                             width: 80, | 
 |                             height: 80, | 
 |                             opacity: 0.5 | 
 |                         } | 
 |                     }), | 
 |                     { | 
 |                         type: 'group', | 
 |                         id: 'gr', | 
 |                         width: 230, | 
 |                         height: 110, | 
 |                         x: 70, | 
 |                         y: 90, | 
 |                         children: [ | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 name: 'rectxx', | 
 |                                 shape: { | 
 |                                     width: 230, | 
 |                                     height: 80 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'red', | 
 |                                     fill: 'transparent', | 
 |                                     lineWidth: 2 | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             }, | 
 |                             { | 
 |                                 id: 'grouptext', | 
 |                                 type: 'text', | 
 |                                 bottom: 0, | 
 |                                 right: 0, | 
 |                                 rotation: 0.5, | 
 |                                 style: { | 
 |                                     text: 'aaa' | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         type: 'text', | 
 |                         bottom: 0, | 
 |                         left: 'center', | 
 |                         style: { | 
 |                             text: 'bbb' | 
 |                         }, | 
 |                         z: 100 | 
 |                     } | 
 |                 ] | 
 |             }); | 
 |  | 
 |             // Set option using getOption | 
 |             const option = chart.getOption(); | 
 |             const graphicOptionList = option.graphic as GraphicComponentOption[]; | 
 |  | 
 |             expect(graphicOptionList.length === 1).toEqual(true); | 
 |             const optionElements = graphicOptionList[0].elements; | 
 |             expect(optionElements && optionElements.length === 5).toEqual(true); | 
 |  | 
 |             expect(optionElements[0].id === 'uriimg' && optionElements[0].parentId == null).toEqual(true); | 
 |             expect(optionElements[1].id === 'gr' && optionElements[1].parentId == null).toEqual(true); | 
 |             expect(optionElements[2].name === 'rectxx' && optionElements[2].parentId === 'gr').toEqual(true); | 
 |             expect((optionElements[3] as any).style.text === 'aaa' && optionElements[3].parentId === 'gr') | 
 |                 .toEqual(true); | 
 |             expect((optionElements[4] as any).style.text === 'bbb' && optionElements[4].parentId == null) | 
 |                 .toEqual(true); | 
 |  | 
 |         }); | 
 |  | 
 |  | 
 |         it('groupSetOptionGetOption', function () { | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: [ | 
 |                     tmpConvertImageOption({ | 
 |                         id: 'uriimg', | 
 |                         type: 'image', | 
 |                         name: 'nameuriimg', | 
 |                         originX: 20, | 
 |                         originY: 20, | 
 |                         left: 10, | 
 |                         top: 10, | 
 |                         style: { | 
 |                             image: imageURI, | 
 |                             width: 80, | 
 |                             height: 80, | 
 |                             opacity: 0.5 | 
 |                         } | 
 |                     }), | 
 |                     { | 
 |                         type: 'group', | 
 |                         id: 'gr', | 
 |                         width: 230, | 
 |                         height: 110, | 
 |                         x: 70, | 
 |                         y: 90, | 
 |                         children: [ | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 name: 'rectxx', | 
 |                                 shape: { | 
 |                                     width: 230, | 
 |                                     height: 80 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'red', | 
 |                                     fill: 'transparent', | 
 |                                     lineWidth: 2 | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             }, | 
 |                             { | 
 |                                 id: 'grouptext', | 
 |                                 type: 'text', | 
 |                                 bottom: 0, | 
 |                                 right: 0, | 
 |                                 rotation: 0.5, | 
 |                                 style: { | 
 |                                     text: 'aaa' | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         type: 'text', | 
 |                         bottom: 0, | 
 |                         left: 'center', | 
 |                         style: { | 
 |                             text: 'bbb' | 
 |                         }, | 
 |                         z: 100 | 
 |                     } | 
 |                 ] | 
 |             }); | 
 |  | 
 |             checkExistsAndRelations(); | 
 |  | 
 |             // Set option using getOption | 
 |             chart.setOption(chart.getOption()); | 
 |  | 
 |             // Check again, should be the same as before. | 
 |             checkExistsAndRelations(); | 
 |  | 
 |             function checkExistsAndRelations() { | 
 |                 const els = getGraphicElements(chart, 'graphic'); | 
 |  | 
 |                 expect(els.length === 6).toEqual(true); | 
 |                 expect(els[0].type === 'group').toEqual(true); | 
 |                 expect(els[1].name === 'nameuriimg').toEqual(true); | 
 |  | 
 |                 expect(els[2].type === 'group').toEqual(true); | 
 |                 const groupEls = getGraphicElements(els[2] as Group, 'graphic'); | 
 |                 expect(groupEls.length === 2).toEqual(true); | 
 |                 expect(groupEls[0] === els[3]).toEqual(true); | 
 |                 expect(groupEls[1] === els[4]).toEqual(true); | 
 |                 expect(els[3].name === 'rectxx').toEqual(true); | 
 |                 expect((els[4] as any).style.text === 'aaa').toEqual(true); | 
 |  | 
 |                 expect((els[5] as any).style.text === 'bbb').toEqual(true); | 
 |             } | 
 |         }); | 
 |  | 
 |  | 
 |         it('onlyOneGraphicComponentAvailable', function () { | 
 |  | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: [ | 
 |                     { | 
 |                         elements: [ | 
 |                             { | 
 |                                 type: 'circle', | 
 |                                 shape: { | 
 |                                     cx: 50, | 
 |                                     cy: 50, | 
 |                                     r: 20 | 
 |                                 } | 
 |                             }, | 
 |                             { | 
 |                                 type: 'circle', | 
 |                                 shape: { | 
 |                                     cx: 150, | 
 |                                     cy: 150, | 
 |                                     r: 20 | 
 |                                 } | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         elements: [ | 
 |                             { | 
 |                                 type: 'circle', | 
 |                                 shape: { | 
 |                                     cx: 100, | 
 |                                     cy: 100, | 
 |                                     r: 20 | 
 |                                 } | 
 |                             } | 
 |                         ] | 
 |                     } | 
 |                 ] | 
 |             }); | 
 |  | 
 |             expect(!!getECModel(chart).getComponent('graphic')).toEqual(true); | 
 |             expect(getECModel(chart).getComponent('graphic', 1) == null).toEqual(true); | 
 |         }); | 
 |  | 
 |  | 
 |         it('replace', function () { | 
 |  | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: { | 
 |                     type: 'circle', | 
 |                     name: 'a', | 
 |                     shape: { | 
 |                         cx: 50, | 
 |                         cy: 50, | 
 |                         r: 20 | 
 |                     }, | 
 |                     style: { | 
 |                         fill: 'green', | 
 |                         stroke: 'pink', | 
 |                         lineWidth: 3 | 
 |                     } | 
 |                 } | 
 |             }); | 
 |  | 
 |             let els: Element[]; | 
 |  | 
 |             els = getGraphicElements(chart, 'graphic'); | 
 |  | 
 |             expect(els.length === 2).toEqual(true); | 
 |             expect(els[0].type === 'group').toEqual(true); | 
 |             expect(els[1].name === 'a' && els[1].type === 'circle').toEqual(true); | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: { | 
 |                     type: 'rect', | 
 |                     $action: 'replace', | 
 |                     name: 'b', | 
 |                     shape: { | 
 |                         x: 50, | 
 |                         y: 50, | 
 |                         width: 20, | 
 |                         height: 60 | 
 |                     }, | 
 |                     style: { | 
 |                         fill: 'green', | 
 |                         stroke: 'pink', | 
 |                         lineWidth: 3 | 
 |                     } | 
 |                 } | 
 |             }); | 
 |  | 
 |             els = getGraphicElements(chart, 'graphic'); | 
 |  | 
 |             expect(els.length === 2).toEqual(true); | 
 |             expect(els[0].type === 'group').toEqual(true); | 
 |             expect(els[1].name === 'b' && els[1].type === 'rect').toEqual(true); | 
 |             expect((els[1] as any).shape && (els[1] as any).shape.width === 20).toEqual(true); | 
 |         }); | 
 |  | 
 |  | 
 |         function getDeleteSourceOption() { | 
 |             return { | 
 |                 graphic: [ | 
 |                     { | 
 |                         type: 'text', | 
 |                         name: 'textname', | 
 |                         style: { | 
 |                             text: 'asdf哈呵', | 
 |                             font: '40px sans-serif', | 
 |                             x: 100, | 
 |                             y: 40 | 
 |                         } | 
 |                     }, | 
 |                     { | 
 |                         id: 'rrr', | 
 |                         name: 'ringname', | 
 |                         type: 'ring', | 
 |                         shape: { | 
 |                             cx: 50, | 
 |                             cy: 150, | 
 |                             r: 20, | 
 |                             r0: 5 | 
 |                         } | 
 |                     }, | 
 |                     { | 
 |                         id: 'xxx', | 
 |                         name: 'rectname', | 
 |                         type: 'rect', | 
 |                         shape: { | 
 |                             x: 250, | 
 |                             y: 50, | 
 |                             width: 20, | 
 |                             height: 80 | 
 |                         } | 
 |                     } | 
 |                 ] | 
 |             }; | 
 |         } | 
 |  | 
 |         function checkDeteteSource(chart: EChartsType) { | 
 |             const els = getGraphicElements(chart, 'graphic'); | 
 |             expect(els.length === 4); | 
 |             expect(els[1].type === 'text' && els[1].name === 'textname').toEqual(true); | 
 |             expect(els[2].type === 'ring' && els[2].name === 'ringname').toEqual(true); | 
 |             expect(els[3].type === 'rect' && els[3].name === 'rectname').toEqual(true); | 
 |         } | 
 |  | 
 |         it('deleteBy$action', function () { | 
 |  | 
 |             chart.setOption(getDeleteSourceOption()); | 
 |  | 
 |             checkDeteteSource(chart); | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: { | 
 |                     id: 'rrr', | 
 |                     $action: 'remove' | 
 |                 } | 
 |             }); | 
 |  | 
 |             const els = getGraphicElements(chart, 'graphic'); | 
 |             expect(els.length === 3); | 
 |             expect(els[1].type === 'text' && els[1].name === 'textname').toEqual(true); | 
 |             expect(els[2].type === 'rect' && els[2].name === 'rectname').toEqual(true); | 
 |         }); | 
 |  | 
 |         it('deleteBySetOptionNotMerge', function () { | 
 |  | 
 |  | 
 |             chart.setOption(getDeleteSourceOption()); | 
 |  | 
 |             checkDeteteSource(chart); | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: { | 
 |                     type: 'rect', | 
 |                     name: 'rectname2', | 
 |                     shape: { | 
 |                         y: 100, | 
 |                         x: 250, | 
 |                         width: 40, | 
 |                         height: 140 | 
 |                     }, | 
 |                     style: { | 
 |                         fill: 'blue' | 
 |                     } | 
 |                 } | 
 |             }, true); | 
 |  | 
 |             const els = getGraphicElements(chart, 'graphic'); | 
 |             expect(els.length === 2); | 
 |             expect(els[1].type === 'rect' && els[1].name === 'rectname2').toEqual(true); | 
 |         }); | 
 |  | 
 |         it('deleteByClear', function () { | 
 |  | 
 |  | 
 |             chart.setOption(getDeleteSourceOption()); | 
 |  | 
 |             checkDeteteSource(chart); | 
 |  | 
 |             chart.clear(); | 
 |  | 
 |             const els = getGraphicElements(chart, 'graphic'); | 
 |             expect(els.length === 0); | 
 |         }); | 
 |  | 
 |  | 
 |         function checkMergeElements(chart: EChartsType, merged: boolean): void { | 
 |             const makeIdentityTransformProps = () => ({ | 
 |                 x: 0, | 
 |                 y: 0, | 
 |                 scaleX: 1, | 
 |                 scaleY: 1, | 
 |                 rotation: 0 | 
 |             }); | 
 |             propHasAll(getGraphicElements(chart, 'graphic'), [ | 
 |                 { | 
 |                     ...makeIdentityTransformProps() | 
 |                 }, | 
 |                 { | 
 |                     ...makeIdentityTransformProps(), | 
 |                     style: {}, | 
 |                     shape: { | 
 |                         x: !merged ? 250 : 350, | 
 |                         y: 50, | 
 |                         width: 20, | 
 |                         height: 80 | 
 |                         // r: 0 | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     ...makeIdentityTransformProps() | 
 |                 }, | 
 |                 { | 
 |                     ...makeIdentityTransformProps(), | 
 |                     style: { | 
 |                         fill: !merged ? 'yellow' : 'pink' | 
 |                     }, | 
 |                     shape: { | 
 |                         x: 30, | 
 |                         y: 30, | 
 |                         width: 10, | 
 |                         height: 20 | 
 |                         // r: 0 | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     ...makeIdentityTransformProps(), | 
 |                     style: !merged | 
 |                         ? {} | 
 |                         : { | 
 |                             fill: 'green' | 
 |                         }, | 
 |                     shape: { | 
 |                         cx: !merged ? 50 : 150, | 
 |                         cy: 150, | 
 |                         r: 20, | 
 |                         r0: 5 | 
 |                     } | 
 |                 } | 
 |             ]); | 
 |         } | 
 |  | 
 |         it('mergeTroughFlatForamt', function () { | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: [ | 
 |                     { | 
 |                         type: 'rect', | 
 |                         shape: { | 
 |                             x: 250, | 
 |                             y: 50, | 
 |                             width: 20, | 
 |                             height: 80 | 
 |                         } | 
 |                     }, | 
 |                     { | 
 |                         type: 'group', | 
 |                         children: [ | 
 |                             { | 
 |                                 id: 'ing', | 
 |                                 type: 'rect', | 
 |                                 shape: { | 
 |                                     x: 30, | 
 |                                     y: 30, | 
 |                                     width: 10, | 
 |                                     height: 20 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     fill: 'yellow' | 
 |                                 } | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         id: 'rrr', | 
 |                         type: 'ring', | 
 |                         shape: { | 
 |                             cx: 50, | 
 |                             cy: 150, | 
 |                             r: 20, | 
 |                             r0: 5 | 
 |                         } | 
 |                     } | 
 |                 ] | 
 |             }); | 
 |  | 
 |             checkMergeElements(chart, false); | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: [ | 
 |                     { | 
 |                         shape: { | 
 |                             x: 350 | 
 |                         } | 
 |                     }, | 
 |                     { | 
 |                         id: 'rrr', | 
 |                         shape: { | 
 |                             cx: 150 | 
 |                         }, | 
 |                         style: { | 
 |                             fill: 'green' | 
 |                         } | 
 |                     }, | 
 |                     // flat mode | 
 |                     { | 
 |                         id: 'ing', | 
 |                         style: { | 
 |                             fill: 'pink' | 
 |                         } | 
 |                     } | 
 |                 ] | 
 |             }); | 
 |  | 
 |             checkMergeElements(chart, true); | 
 |         }); | 
 |  | 
 |  | 
 |     }); | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |     describe('groupLRTB', function () { | 
 |  | 
 |         function getOption() { | 
 |             return { | 
 |                 graphic: [ | 
 |                     { | 
 |                         type: 'text', | 
 |                         bottom: 0, | 
 |                         right: 0, | 
 |                         rotation: Math.PI / 4, | 
 |                         style: { | 
 |                             font: '24px Microsoft YaHei', | 
 |                             text: '全屏右下角' | 
 |                         }, | 
 |                         z: 100 | 
 |                     }, | 
 |                     tmpConvertImageOption({ | 
 |                         id: 'uriimg', | 
 |                         type: 'image', | 
 |                         originX: 20, | 
 |                         originY: 20, | 
 |                         left: 10, | 
 |                         top: 10, | 
 |                         style: { | 
 |                             image: imageURI, | 
 |                             width: 80, | 
 |                             height: 80, | 
 |                             opacity: 0.5 | 
 |                         } | 
 |                     }), | 
 |                     { | 
 |                         type: 'group', | 
 |                         id: 'gr', | 
 |                         width: 230, | 
 |                         height: 110, | 
 |                         x: 70, | 
 |                         y: 90, | 
 |                         children: [ | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 shape: { | 
 |                                     width: 230, | 
 |                                     height: 80 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'red', | 
 |                                     fill: 'transparent', | 
 |                                     lineWidth: 2 | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             }, | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 shape: { | 
 |                                     width: 60, | 
 |                                     height: 110 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'red', | 
 |                                     fill: 'transparent', | 
 |                                     lineWidth: 2 | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             }, | 
 |                             { | 
 |                                 id: 'grouptext', | 
 |                                 type: 'text', | 
 |                                 bottom: 0, | 
 |                                 right: 0, | 
 |                                 rotation: 0.5, | 
 |                                 style: { | 
 |                                     font: '14px Microsoft YaHei', | 
 |                                     text: 'group最右下角' | 
 |                                 }, | 
 |                                 z: 100 | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         type: 'text', | 
 |                         bottom: 0, | 
 |                         left: 'center', | 
 |                         style: { | 
 |                             font: '18px sans-serif', | 
 |                             text: '全屏最下中间\n这是多行文字\n这是第三行' | 
 |                         }, | 
 |                         z: 100 | 
 |                     } | 
 |                 ] | 
 |             }; | 
 |         } | 
 |  | 
 |         function checkLocations(chart: EChartsType, uriimgChanged?: boolean) { | 
 |  | 
 |             propHasAll(getGraphicElements(chart, 'graphic'), [ | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0 | 
 |                 }, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 98.17662350913716, | 
 |                     y: 133.02943725152284, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0.7853981633974483, | 
 |                     style: { | 
 |                         font: '24px Microsoft YaHei', | 
 |                         text: '全屏右下角', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */}, | 
 |                 !uriimgChanged | 
 |                     ? tmpConvertImageOption({ | 
 |                         x: 10, | 
 |                         y: 10, | 
 |                         scaleX: 1, | 
 |                         scaleY: 1, | 
 |                         rotation: 0, | 
 |                         style: { | 
 |                             height: 80, | 
 |                             opacity: 0.5, | 
 |                             width: 80, | 
 |                             image: imageURI | 
 |                         } | 
 |                     }) | 
 |                     : tmpConvertImageOption({ | 
 |                         x: 61, | 
 |                         y: 45, | 
 |                         scaleX: 1, | 
 |                         scaleY: 1, | 
 |                         rotation: 0, | 
 |                         style: { | 
 |                             height: 60, | 
 |                             opacity: 0.5, | 
 |                             width: 78, | 
 |                             image: imageURI | 
 |                         } | 
 |                     }), | 
 |                 { | 
 |                     x: 70, | 
 |                     y: 90, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0 | 
 |                 }, | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'red', | 
 |                         fill: 'transparent', | 
 |                         lineWidth: 2 | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 230, | 
 |                         height: 80, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'red', | 
 |                         fill: 'transparent', | 
 |                         lineWidth: 2 | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 60, | 
 |                         height: 110, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 145.47972137162424, | 
 |                     y: 97.71384413353478, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0.5, | 
 |                     style: { | 
 |                         font: '14px Microsoft YaHei', | 
 |                         text: 'group最右下角', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */}, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 46, | 
 |                     y: 96, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         font: '18px sans-serif', | 
 |                         text: '全屏最下中间\n这是多行文字\n这是第三行', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */} | 
 |             ]); | 
 |         } | 
 |  | 
 |         function checkResizedLocations(chart: EChartsType) { | 
 |             propHasAll(getGraphicElements(chart, 'graphic'), [ | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0 | 
 |                 }, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 98.17662350913716, | 
 |                     y: 133.02943725152286, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0.7853981633974483, | 
 |                     style: { | 
 |                         font: '24px Microsoft YaHei', | 
 |                         text: '全屏右下角', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */}, | 
 |                 tmpConvertImageOption({ | 
 |                     x: 10, | 
 |                     y: 10, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         image: imageURI, | 
 |                         width: 80, | 
 |                         height: 80, | 
 |                         opacity: 0.5 | 
 |                     } | 
 |                 }), | 
 |                 { | 
 |                     x: 70, | 
 |                     y: 90, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0 | 
 |                 }, | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'red', | 
 |                         fill: 'transparent', | 
 |                         lineWidth: 2 | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 230, | 
 |                         height: 80, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'red', | 
 |                         fill: 'transparent', | 
 |                         lineWidth: 2 | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 60, | 
 |                         height: 110, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 145.47972137162424, | 
 |                     y: 97.71384413353478, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0.5, | 
 |                     style: { | 
 |                         font: '14px Microsoft YaHei', | 
 |                         text: 'group最右下角', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */}, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: 46, | 
 |                     y: 96, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         font: '18px sans-serif', | 
 |                         text: '全屏最下中间\n这是多行文字\n这是第三行', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */} | 
 |             ]); | 
 |         } | 
 |  | 
 |         it('getAndGet', function () { | 
 |             const myChart = createChart({ | 
 |                 width: 200, | 
 |                 height: 150 | 
 |             }); | 
 |             myChart.setOption(getOption()); | 
 |  | 
 |             checkLocations(myChart); | 
 |             // Set option using getOption | 
 |             chart.setOption(myChart.getOption()); | 
 |             // Check again, should be the same as before. | 
 |             checkLocations(myChart); | 
 |  | 
 |             myChart.dispose(); | 
 |         }); | 
 |  | 
 |         // Test modify location by setOption. | 
 |         // And test center and middle. | 
 |         it('modifyAndCenter', function () { | 
 |             const myChart = createChart({ | 
 |                 width: 200, | 
 |                 height: 150 | 
 |             }); | 
 |  | 
 |             myChart.setOption(getOption()); | 
 |  | 
 |             checkLocations(myChart); | 
 |  | 
 |             myChart.setOption({ | 
 |                 graphic: [tmpConvertImageOption({ | 
 |                     id: 'uriimg', | 
 |                     left: 'center', | 
 |                     top: 'middle', | 
 |                     style: { | 
 |                         width: 78, | 
 |                         height: 60 | 
 |                     } | 
 |                 })] | 
 |             }); | 
 |  | 
 |             checkLocations(myChart, true); | 
 |  | 
 |             myChart.dispose(); | 
 |         }); | 
 |  | 
 |         it('resize', function () { | 
 |             const myChart = createChart({ | 
 |                 width: 200, | 
 |                 height: 150 | 
 |             }); | 
 |  | 
 |             myChart.setOption(getOption()); | 
 |  | 
 |             checkLocations(myChart); | 
 |  | 
 |             myChart.resize({ | 
 |                 width: 220, | 
 |                 height: 300 | 
 |             }); | 
 |  | 
 |             checkResizedLocations(myChart); | 
 |  | 
 |             myChart.dispose(); | 
 |         }); | 
 |     }); | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |     describe('boundingAndRotation', function () { | 
 |  | 
 |         function getOption(): EChartsOption { | 
 |             return { | 
 |                 legend: { | 
 |                     data: ['高度(km)与气温(°C)变化关系'] | 
 |                 }, | 
 |                 xAxis: { | 
 |                 }, | 
 |                 yAxis: { | 
 |                     type: 'category', | 
 |                     data: ['0', '10', '20', '30', '40', '50', '60', '70', '80'] | 
 |                 }, | 
 |                 graphic: [ | 
 |                     tmpConvertImageOption({ | 
 |                         type: 'image', | 
 |                         id: 'img', | 
 |                         z: -10, | 
 |                         right: 0, | 
 |                         top: 0, | 
 |                         bounding: 'raw', | 
 |                         originX: 75, | 
 |                         originY: 75, | 
 |                         style: { | 
 |                             fill: '#000', | 
 |                             image: imageURI, | 
 |                             width: 150, | 
 |                             height: 150, | 
 |                             opacity: 0.4 | 
 |                         } as any | 
 |                     }), | 
 |                     { | 
 |                         type: 'group', | 
 |                         id: 'rectgroup1', | 
 |                         bottom: 0, | 
 |                         right: 0, | 
 |                         bounding: 'raw', | 
 |                         children: [ | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 left: 'center', | 
 |                                 top: 'center', | 
 |                                 shape: { | 
 |                                     width: 20, | 
 |                                     height: 80 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'green', | 
 |                                     fill: 'transparent' | 
 |                                 } | 
 |                             }, | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 left: 'center', | 
 |                                 top: 'center', | 
 |                                 shape: { | 
 |                                     width: 80, | 
 |                                     height: 20 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     stroke: 'green', | 
 |                                     fill: 'transparent' | 
 |                                 } | 
 |                             } | 
 |                         ] | 
 |                     }, | 
 |                     { | 
 |                         type: 'rect', | 
 |                         id: 'rect2', | 
 |                         bottom: 0, | 
 |                         right: 'center', | 
 |                         shape: { | 
 |                             width: 50, | 
 |                             height: 80 | 
 |                         }, | 
 |                         style: { | 
 |                             stroke: 'green', | 
 |                             fill: 'transparent' | 
 |                         } | 
 |                     }, | 
 |                     { | 
 |                         type: 'group', | 
 |                         id: 'textGroup1', | 
 |                         left: '10%', | 
 |                         top: 'center', | 
 |                         scaleX: 1, | 
 |                         scaleY: 0.5, | 
 |                         children: [ | 
 |                             { | 
 |                                 type: 'rect', | 
 |                                 z: 100, | 
 |                                 left: 'center', | 
 |                                 top: 'center', | 
 |                                 shape: { | 
 |                                     width: 170, | 
 |                                     height: 70 | 
 |                                 }, | 
 |                                 style: { | 
 |                                     fill: '#fff', | 
 |                                     stroke: '#999', | 
 |                                     lineWidth: 2, | 
 |                                     shadowBlur: 8, | 
 |                                     shadowOffsetX: 3, | 
 |                                     shadowOffsetY: 3, | 
 |                                     shadowColor: 'rgba(0,0,0,0.3)' | 
 |                                 } | 
 |                             }, | 
 |                             { | 
 |                                 type: 'text', | 
 |                                 z: 100, | 
 |                                 top: 'middle', | 
 |                                 left: 'center', | 
 |                                 style: { | 
 |                                     text: [ | 
 |                                         '横轴表示温度,单位是°C', | 
 |                                         '纵轴表示高度,单位是km', | 
 |                                         '右上角有一个图片做的水印' | 
 |                                     ].join('\n'), | 
 |                                     font: '12px Microsoft YaHei' | 
 |                                 } | 
 |                             } | 
 |                         ] | 
 |                     } | 
 |                 ], | 
 |                 series: [ | 
 |                     { | 
 |                         name: '高度(km)与气温(°C)变化关系', | 
 |                         type: 'line', | 
 |                         data: [15, -50, -56.5, -46.5, -22.1, -2.5, -27.7, -55.7, -76.5] | 
 |                     } | 
 |                 ] | 
 |             }; | 
 |         } | 
 |  | 
 |         function checkLocations(chart: EChartsType, rotated?: boolean) { | 
 |             propHasAll(getGraphicElements(chart, 'graphic'), [ | 
 |                 { | 
 |                     x: 0, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0 | 
 |                 }, | 
 |                 tmpConvertImageOption({ | 
 |                     x: 350, | 
 |                     y: 0, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: !rotated ? 0 : 0.6283185307179586, | 
 |                     style: { | 
 |                         // fill: '#000', | 
 |                         image: imageURI, | 
 |                         width: 150, | 
 |                         height: 150, | 
 |                         opacity: 0.4 | 
 |                     } | 
 |                 }), | 
 |                 { | 
 |                     x: 500, | 
 |                     y: 400, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: !rotated ? 0 : 0.6283185307179586 | 
 |                 }, | 
 |                 { | 
 |                     x: -10, | 
 |                     y: -40, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'green', | 
 |                         fill: 'transparent' | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 20, | 
 |                         height: 80, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     x: -40, | 
 |                     y: -10, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         stroke: 'green', | 
 |                         fill: 'transparent' | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 80, | 
 |                         height: 20, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     x: !rotated ? 225 : 206.2631650489274, | 
 |                     y: !rotated ? 319.5 : 334.5802393266705, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: !rotated ? 0 : 0.6283185307179586, | 
 |                     style: { | 
 |                         stroke: 'green', | 
 |                         fill: 'transparent' | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 50, | 
 |                         height: 80, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 { | 
 |                     x: !rotated ? 136 : 130.15559605751, | 
 |                     y: 200, | 
 |                     scaleX: 1, | 
 |                     scaleY: 0.5, | 
 |                     rotation: !rotated ? 0 : 0.6283185307179586 | 
 |                 }, | 
 |                 { | 
 |                     x: -85, | 
 |                     y: -35, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         fill: '#fff', | 
 |                         stroke: '#999', | 
 |                         lineWidth: 2, | 
 |                         shadowBlur: 8, | 
 |                         shadowOffsetX: 3, | 
 |                         shadowOffsetY: 3, | 
 |                         shadowColor: 'rgba(0,0,0,0.3)' | 
 |                     }, | 
 |                     shape: { | 
 |                         width: 170, | 
 |                         height: 70, | 
 |                         x: 0, | 
 |                         y: 0 | 
 |                         // r: 0, | 
 |                     } | 
 |                 }, | 
 |                 {/* FIXME: node-canvas measure issue casue behavior different from browser. comment out it temporarily. | 
 |                     x: -72, | 
 |                     y: -18, | 
 |                     scaleX: 1, | 
 |                     scaleY: 1, | 
 |                     rotation: 0, | 
 |                     style: { | 
 |                         text: '横轴表示温度,单位是°C\n纵轴表示高度,单位是km\n右上角有一个图片做的水印', | 
 |                         font: '12px Microsoft YaHei', | 
 |                         textVerticalAlign: null, | 
 |                         verticalAlign: null | 
 |                     } | 
 |                 */} | 
 |             ]); | 
 |         } | 
 |  | 
 |         it('bounding', function () { | 
 |  | 
 |  | 
 |             chart.setOption(getOption()); | 
 |  | 
 |             checkLocations(chart); | 
 |  | 
 |             // Set option using getOption | 
 |             chart.setOption(chart.getOption()); | 
 |  | 
 |             // Check again, should be the same as before. | 
 |             checkLocations(chart); | 
 |  | 
 |             const rotation = Math.PI / 5; | 
 |  | 
 |             chart.setOption({ | 
 |                 graphic: [{ | 
 |                     id: 'img', | 
 |                     bounding: 'raw', | 
 |                     originX: 75, | 
 |                     originY: 75, | 
 |                     rotation: rotation | 
 |                 } as any, { | 
 |                     id: 'rectgroup1', | 
 |                     rotation: rotation | 
 |                 }, { | 
 |                     id: 'rect2', | 
 |                     rotation: rotation | 
 |                 }, { | 
 |                     id: 'textGroup1', | 
 |                     rotation: rotation | 
 |                 }] | 
 |             }); | 
 |  | 
 |             checkLocations(chart, true); | 
 |  | 
 |         }); | 
 |  | 
 |     }); | 
 |  | 
 | }); |