private _relocate()

in src/component/graphic/GraphicView.ts [280:365]


    private _relocate(graphicModel: GraphicComponentModel, api: ExtensionAPI): void {
        const elOptions = graphicModel.option.elements;
        const rootGroup = this.group;
        const elMap = this._elMap;
        const apiWidth = api.getWidth();
        const apiHeight = api.getHeight();

        const xy = ['x', 'y'] as const;

        // Top-down to calculate percentage width/height of group
        for (let i = 0; i < elOptions.length; i++) {
            const elOption = elOptions[i];
            const id = modelUtil.convertOptionIdName(elOption.id, null);
            const el = id != null ? elMap.get(id) : null;

            if (!el || !el.isGroup) {
                continue;
            }
            const parentEl = el.parent;
            const isParentRoot = parentEl === rootGroup;
            // Like 'position:absolut' in css, default 0.
            const elInner = inner(el);
            const parentElInner = inner(parentEl);
            elInner.width = parsePercent(
                (elInner.option as GraphicComponentGroupOption).width,
                isParentRoot ? apiWidth : parentElInner.width
            ) || 0;
            elInner.height = parsePercent(
                (elInner.option as GraphicComponentGroupOption).height,
                isParentRoot ? apiHeight : parentElInner.height
            ) || 0;
        }

        // Bottom-up tranvese all elements (consider ec resize) to locate elements.
        for (let i = elOptions.length - 1; i >= 0; i--) {
            const elOption = elOptions[i];
            const id = modelUtil.convertOptionIdName(elOption.id, null);
            const el = id != null ? elMap.get(id) : null;

            if (!el) {
                continue;
            }

            const parentEl = el.parent;
            const parentElInner = inner(parentEl);
            const containerInfo = parentEl === rootGroup
                ? {
                    width: apiWidth,
                    height: apiHeight
                }
                : {
                    width: parentElInner.width,
                    height: parentElInner.height
                };

            // PENDING
            // Currently, when `bounding: 'all'`, the union bounding rect of the group
            // does not include the rect of [0, 0, group.width, group.height], which
            // is probably weird for users. Should we make a break change for it?
            const layoutPos = {} as Record<'x' | 'y', number>;
            const layouted = layoutUtil.positionElement(
                el, elOption, containerInfo, null,
                { hv: elOption.hv, boundingMode: elOption.bounding },
                layoutPos
            );

            if (!inner(el).isNew && layouted) {
                const transition = elOption.transition;
                const animatePos = {} as Record<'x' | 'y', number>;
                for (let k = 0; k < xy.length; k++) {
                    const key = xy[k];
                    const val = layoutPos[key];
                    if (transition && (isTransitionAll(transition) || zrUtil.indexOf(transition, key) >= 0)) {
                        animatePos[key] = val;
                    }
                    else {
                        el[key] = val;
                    }
                }
                updateProps(el, animatePos, graphicModel, 0);
            }
            else {
                el.attr(layoutPos);
            }
        }
    }