private _renderNormal()

in src/chart/bar/BarView.ts [193:461]


    private _renderNormal(
        seriesModel: BarSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: Payload
    ): void {
        const group = this.group;
        const data = seriesModel.getData();
        const oldData = this._data;

        const coord = seriesModel.coordinateSystem;
        const baseAxis = coord.getBaseAxis();
        let isHorizontalOrRadial: boolean;

        if (coord.type === 'cartesian2d') {
            isHorizontalOrRadial = (baseAxis as Axis2D).isHorizontal();
        }
        else if (coord.type === 'polar') {
            isHorizontalOrRadial = baseAxis.dim === 'angle';
        }

        const animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;

        const realtimeSortCfg = shouldRealtimeSort(seriesModel, coord);

        if (realtimeSortCfg) {
            this._enableRealtimeSort(realtimeSortCfg, data, api);
        }

        const needsClip = seriesModel.get('clip', true) || realtimeSortCfg;
        const coordSysClipArea = getClipArea(coord, data);
        // If there is clipPath created in large mode. Remove it.
        group.removeClipPath();
        // We don't use clipPath in normal mode because we needs a perfect animation
        // And don't want the label are clipped.

        const roundCap = seriesModel.get('roundCap', true);

        const drawBackground = seriesModel.get('showBackground', true);
        const backgroundModel = seriesModel.getModel('backgroundStyle');
        const barBorderRadius = backgroundModel.get('borderRadius') || 0;

        const bgEls: BarView['_backgroundEls'] = [];
        const oldBgEls = this._backgroundEls;

        const isInitSort = payload && payload.isInitSort;
        const isChangeOrder = payload && payload.type === 'changeAxisOrder';

        function createBackground(dataIndex: number) {
            const bgLayout = getLayout[coord.type](data, dataIndex);
            const bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
            bgEl.useStyle(backgroundModel.getItemStyle());
            // Only cartesian2d support borderRadius.
            if (coord.type === 'cartesian2d') {
                (bgEl as Rect).setShape('r', barBorderRadius);
            }
            else {
                (bgEl as Sector).setShape('cornerRadius', barBorderRadius);
            }
            bgEls[dataIndex] = bgEl;
            return bgEl;
        };
        data.diff(oldData)
            .add(function (dataIndex) {
                const itemModel = data.getItemModel<BarDataItemOption>(dataIndex);
                const layout = getLayout[coord.type](data, dataIndex, itemModel);

                if (drawBackground) {
                    createBackground(dataIndex);
                }

                // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
                if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) {
                    return;
                }

                let isClipped = false;
                if (needsClip) {
                    // Clip will modify the layout params.
                    // And return a boolean to determine if the shape are fully clipped.
                    isClipped = clip[coord.type](coordSysClipArea, layout);
                }

                const el = elementCreator[coord.type](
                    seriesModel,
                    data,
                    dataIndex,
                    layout,
                    isHorizontalOrRadial,
                    animationModel,
                    baseAxis.model,
                    false,
                    roundCap
                );
                if (realtimeSortCfg) {
                    /**
                     * Force label animation because even if the element is
                     * ignored because it's clipped, it may not be clipped after
                     * changing order. Then, if not using forceLabelAnimation,
                     * the label animation was never started, in which case,
                     * the label will be the final value and doesn't have label
                     * animation.
                     */
                    (el as ECElement).forceLabelAnimation = true;
                }

                updateStyle(
                    el, data, dataIndex, itemModel, layout,
                    seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                );
                if (isInitSort) {
                    (el as Rect).attr({ shape: layout });
                }
                else if (realtimeSortCfg) {
                    updateRealtimeAnimation(
                        realtimeSortCfg,
                        animationModel,
                        el as Rect,
                        layout as LayoutRect,
                        dataIndex,
                        isHorizontalOrRadial,
                        false,
                        false
                    );
                }
                else {
                    initProps(el, {shape: layout} as any, seriesModel, dataIndex);
                }

                data.setItemGraphicEl(dataIndex, el);

                group.add(el);
                el.ignore = isClipped;
            })
            .update(function (newIndex, oldIndex) {
                const itemModel = data.getItemModel<BarDataItemOption>(newIndex);
                const layout = getLayout[coord.type](data, newIndex, itemModel);

                if (drawBackground) {
                    let bgEl: Rect | Sector;
                    if (oldBgEls.length === 0) {
                        bgEl = createBackground(oldIndex);
                    }
                    else {
                        bgEl = oldBgEls[oldIndex];
                        bgEl.useStyle(backgroundModel.getItemStyle());
                        // Only cartesian2d support borderRadius.
                        if (coord.type === 'cartesian2d') {
                            (bgEl as Rect).setShape('r', barBorderRadius);
                        }
                        else {
                            (bgEl as Sector).setShape('cornerRadius', barBorderRadius);
                        }
                        bgEls[newIndex] = bgEl;
                    }
                    const bgLayout = getLayout[coord.type](data, newIndex);
                    const shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
                    updateProps<RectProps | SectorProps>(bgEl, { shape }, animationModel, newIndex);
                }

                let el = oldData.getItemGraphicEl(oldIndex) as BarPossiblePath;
                if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) {
                    group.remove(el);
                    return;
                }

                let isClipped = false;
                if (needsClip) {
                    isClipped = clip[coord.type](coordSysClipArea, layout);
                    if (isClipped) {
                        group.remove(el);
                    }
                }

                const roundCapChanged = el && (el.type === 'sector' && roundCap || el.type === 'sausage' && !roundCap);
                if (roundCapChanged) {
                    // roundCap changed, there is no way to use animation from a `sector` to a `sausage` shape,
                    // so remove the old one and create a new shape
                    el && removeElementWithFadeOut(el, seriesModel, oldIndex);
                    el = null;
                }

                if (!el) {
                    el = elementCreator[coord.type](
                        seriesModel,
                        data,
                        newIndex,
                        layout,
                        isHorizontalOrRadial,
                        animationModel,
                        baseAxis.model,
                        true,
                        roundCap
                    );
                }
                else {
                    saveOldStyle(el);
                }

                if (realtimeSortCfg) {
                    (el as ECElement).forceLabelAnimation = true;
                }

                if (isChangeOrder) {
                    const textEl = el.getTextContent();
                    if (textEl) {
                        const labelInnerStore = labelInner(textEl);
                        if (labelInnerStore.prevValue != null) {
                            /**
                             * Set preValue to be value so that no new label
                             * should be started, otherwise, it will take a full
                             * `animationDurationUpdate` time to finish the
                             * animation, which is not expected.
                             */
                            labelInnerStore.prevValue = labelInnerStore.value;
                        }
                    }
                }
                // Not change anything if only order changed.
                // Especially not change label.
                else {
                    updateStyle(
                        el, data, newIndex, itemModel, layout,
                        seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                    );
                }

                if (isInitSort) {
                    (el as Rect).attr({ shape: layout });
                }
                else if (realtimeSortCfg) {
                    updateRealtimeAnimation(
                        realtimeSortCfg,
                        animationModel,
                        el as Rect,
                        layout as LayoutRect,
                        newIndex,
                        isHorizontalOrRadial,
                        true,
                        isChangeOrder
                    );
                }
                else {
                    updateProps(el, {
                        shape: layout
                    } as any, seriesModel, newIndex, null);
                }

                data.setItemGraphicEl(newIndex, el);
                el.ignore = isClipped;
                group.add(el);
            })
            .remove(function (dataIndex) {
                const el = oldData.getItemGraphicEl(dataIndex) as Path;
                el && removeElementWithFadeOut(el, seriesModel, dataIndex);
            })
            .execute();

        const bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
        bgGroup.removeAll();

        for (let i = 0; i < bgEls.length; ++i) {
            bgGroup.add(bgEls[i]);
        }
        group.add(bgGroup);
        this._backgroundEls = bgEls;

        this._data = data;
    }