private render()

in src/visual.ts [1885:2155]


    private render(suppressAnimations: boolean = true): void {
        this.setVisibility(true);

        this.legendMargins = this.legendMargins || this.legend.getMargins();

        if (this.legend.isVisible()) {
            this.legendMargins = this.legend.getMargins();
        }

        const viewport: IViewport = {
            height: this.currentViewport.height - this.legendMargins.height,
            width: this.currentViewport.width - this.legendMargins.width
        };

        const maxMarginFactor: number = this.getMaxMarginFactor(),
            leftRightMarginLimit: number
                = this.leftRightMarginLimit
                = viewport.width * maxMarginFactor;

        this.bottomMarginLimit = Math.max(
            MekkoChart.MinBottomMargin,
            Math.ceil(viewport.height * maxMarginFactor));

        const xAxisTextProperties: TextProperties = MekkoChart.getTextProperties(this.categoryAxisProperties
            && PixelConverter.fromPointToPixel(
                parseFloat(<any>this.categoryAxisProperties["fontSize"])) || undefined);

        const y1AxisTextProperties: TextProperties = MekkoChart.getTextProperties(this.valueAxisProperties
            && PixelConverter.fromPointToPixel(
                parseFloat(<any>this.valueAxisProperties["fontSize"])) || undefined);

        const margin: IMargin = this.margin;

        // reset defaults
        margin.top = parseFloat(y1AxisTextProperties.fontSize) / MekkoChart.MarginTopFactor;
        margin.bottom = MekkoChart.MinBottomMargin;
        margin.right = 0;

        let axes: MekkoChartAxisProperties = this.axes = axisUtils.calculateAxes(
            this.layers,
            viewport,
            margin,
            this.categoryAxisProperties,
            this.valueAxisProperties,
            this.isXScrollBarVisible || this.isYScrollBarVisible,
            null);

        this.yAxisIsCategorical = axes.y1.isCategoryAxis;

        this.hasCategoryAxis = this.yAxisIsCategorical
            ? axes.y1 && axes.y1.values.length > 0
            : axes.x && axes.x.values.length > 0;

        const renderXAxis: boolean = this.shouldRenderAxis(axes.x),
            renderY1Axis: boolean = this.shouldRenderAxis(axes.y1),
            renderY2Axis: boolean = this.shouldRenderSecondaryAxis(axes.y2);

        let width: number = viewport.width - (margin.left + margin.right),
            isScalar: boolean = false,
            mainAxisScale,
            preferredViewport: IViewport;

        this.isXScrollBarVisible = false;
        this.isYScrollBarVisible = false;

        const yAxisOrientation: string = this.yAxisOrientation,
            showY1OnRight: boolean = yAxisOrientation === axisPosition.right;

        if (this.layers) {
            if (this.layers[0].getVisualCategoryAxisIsScalar) {
                isScalar = this.layers[0].getVisualCategoryAxisIsScalar();
            }

            if (!isScalar && this.isScrollable && this.layers[0].getPreferredPlotArea) {
                const categoryThickness: number = this.scrollX
                    ? axes.x.categoryThickness
                    : axes.y1.categoryThickness;

                const categoryCount: number = this.scrollX
                    ? axes.x.values.length
                    : axes.y1.values.length;

                preferredViewport = this.layers[0].getPreferredPlotArea(
                    isScalar,
                    categoryCount,
                    categoryThickness);

                if (this.scrollX
                    && preferredViewport
                    && preferredViewport.width > viewport.width) {

                    this.isXScrollBarVisible = true;

                    viewport.height -= MekkoChart.ScrollBarWidth;
                }

                if (this.scrollY
                    && preferredViewport
                    && preferredViewport.height > viewport.height) {

                    this.isYScrollBarVisible = true;

                    viewport.width -= MekkoChart.ScrollBarWidth;
                    width = viewport.width - (margin.left + margin.right);
                }
            }
        }

        // Only create the g tag where there is a scrollbar
        if (this.isXScrollBarVisible || this.isYScrollBarVisible) {
            if (!this.brushGraphicsContext) {
                this.brushGraphicsContext = this.svg.append("g")
                    .classed(MekkoChart.XBrushSelector.className, true);
            }
        }
        else {
            // clear any existing brush if no scrollbar is shown
            this.svg
                .selectAll(MekkoChart.BrushSelector.selectorName)
                .remove();

            this.brushGraphicsContext = undefined;
        }

        // Recalculate axes now that scrollbar visible variables have been set
        axes = axisUtils.calculateAxes(
            this.layers,
            viewport,
            margin,
            this.categoryAxisProperties,
            this.valueAxisProperties,
            this.isXScrollBarVisible || this.isYScrollBarVisible,
            null);

        // we need to make two passes because the margin changes affect the chosen tick values, which then affect the margins again.
        // after the second pass the margins are correct.
        let doneWithMargins: boolean = false,
            maxIterations: number = 2,
            numIterations: number = 0,
            tickLabelMargins: TickLabelMargins = undefined,
            chartHasAxisLabels: boolean = undefined,
            axisLabels: MekkoChartAxesLabels = undefined;

        while (!doneWithMargins && numIterations < maxIterations) {
            numIterations++;

            tickLabelMargins = labelUtils.getTickLabelMargins(
                { width, height: viewport.height },
                leftRightMarginLimit,
                textMeasurementService.measureSvgTextWidth,
                textMeasurementService.estimateSvgTextHeight,
                axes,
                this.bottomMarginLimit,
                xAxisTextProperties,
                y1AxisTextProperties,
                null,
                false,
                this.isXScrollBarVisible || this.isYScrollBarVisible,
                showY1OnRight,
                renderXAxis,
                renderY1Axis,
                renderY2Axis);

            // We look at the y axes as main and second sides, if the y axis orientation is right so the main side represents the right side
            let maxMainYaxisSide: number = showY1OnRight
                ? tickLabelMargins.yRight
                : tickLabelMargins.yLeft;

            let maxSecondYaxisSide: number = showY1OnRight
                ? tickLabelMargins.yLeft
                : tickLabelMargins.yRight;

            let xMax: number = renderXAxis
                ? (tickLabelMargins.xMax / MekkoChart.TickLabelMarginsXMaxFactor)
                : 0;

            maxMainYaxisSide += MekkoChart.LeftPadding;
            maxSecondYaxisSide += MekkoChart.RightPadding;
            xMax += MekkoChart.BottomPadding;

            const rotataionEnabled = (<BaseColumnChart>this.layers[0]).getXAxisLabelsSettings().enableRotataion;

            if (rotataionEnabled) {
                let axes: MekkoChartAxisProperties = this.axes = axisUtils.calculateAxes(
                    this.layers,
                    this.currentViewport,
                    this.margin,
                    this.categoryAxisProperties,
                    this.valueAxisProperties,
                    this.isXScrollBarVisible || this.isYScrollBarVisible,
                    null);

                xMax += this.calculateXAxisAdditionalHeight(axes.x.values);
            }

            if (this.hideAxisLabels(this.legendMargins)) {
                axes.x.axisLabel = null;
                axes.y1.axisLabel = null;

                if (axes.y2) {
                    axes.y2.axisLabel = null;
                }
            }

            this.addUnitTypeToAxisLabel(axes);
            axisLabels = {
                x: axes.x.axisLabel,
                y: axes.y1.axisLabel,
                y2: axes.y2
                    ? axes.y2.axisLabel
                    : null
            };

            chartHasAxisLabels = (axisLabels.x != null)
                || (axisLabels.y != null || axisLabels.y2 != null);

            if (axisLabels.x != null) {
                xMax += MekkoChart.XAxisLabelPadding;
            }

            if (axisLabels.y != null) {
                maxMainYaxisSide += MekkoChart.YAxisLabelPadding;
            }

            if (axisLabels.y2 != null) {
                maxSecondYaxisSide += MekkoChart.YAxisLabelPadding;
            }

            margin.left = showY1OnRight
                ? maxSecondYaxisSide
                : maxMainYaxisSide;

            margin.right = showY1OnRight
                ? maxMainYaxisSide
                : maxSecondYaxisSide;

            margin.bottom = xMax;

            this.margin = margin;

            width = viewport.width - (margin.left + margin.right);

            // re-calculate the axes with the new margins
            const previousTickCountY1: number = axes.y1.values.length,
                previousTickCountY2: number = axes.y2 && axes.y2.values.length;

            axes = axisUtils.calculateAxes(
                this.layers,
                viewport,
                margin,
                this.categoryAxisProperties,
                this.valueAxisProperties,
                this.isXScrollBarVisible || this.isYScrollBarVisible,
                axes);

            if (axes.y1.values.length === previousTickCountY1
                && (!axes.y2 || axes.y2.values.length === previousTickCountY2)) {
                doneWithMargins = true;
            }
        }

        this.renderChart(
            mainAxisScale,
            axes,
            width,
            tickLabelMargins,
            chartHasAxisLabels,
            axisLabels,
            viewport,
            suppressAnimations);
    }