private getForceTick()

in src/visual.ts [839:901]


    private getForceTick(): () => void {
        const viewport: IViewport = this.viewportIn;
        const properties: TextProperties = {
            fontFamily: ForceGraph.LabelsFontFamily,
            fontSize: PixelConverter.fromPoint(this.settings.labels.fontSize),
            text: this.data.formatter.format("")
        };

        const showArrow: boolean = this.settings && this.settings.links && this.settings.links.showArrow;

        let resolutionFactor: number = ForceGraph.ResolutionFactor;
        if (this.settings.size.boundedByBox) {
            resolutionFactor = ForceGraph.ResolutionFactorBoundByBox;
        }
        // limitX and limitY is necessary when you minimize the graph and then resize it to normal.
        // "width/height * 20" seems enough to move nodes freely by force layout.
        const maxWidth: number = viewport.width * resolutionFactor,
            maxHeight: number = viewport.height * resolutionFactor,
            viewPortWidthDownLimit: number = (viewport.width - maxWidth) / 2,
            viewPortHeightDownLimit: number = (viewport.height - maxHeight) / 2,
            viewPortHeightUpLimit: number = (viewport.height + maxHeight) / 2,
            viewPortWidthUpLimit: number = (viewport.height + maxHeight) / 2,
            limitX: (x: number) => number = x => Math.max(viewPortWidthDownLimit, Math.min(viewPortWidthUpLimit, x)),
            limitY: (y: number) => number = y => Math.max(viewPortHeightDownLimit, Math.min(viewPortWidthUpLimit, y));

        return () => {
            this.paths.attr("d", (link: ForceGraphLink) => {
                link.source.x = limitX(link.source.x);
                link.source.y = limitY(link.source.y);
                link.target.x = limitX(link.target.x);
                link.target.y = limitY(link.target.y);

                return showArrow
                    ? this.getPathWithArrow(link)
                    : this.getPathWithoutArrow(link);
            });

            this.nodes.attr("transform", (node: ForceGraphNode) => translate(limitX(node.x), limitY(node.y)));

            if (!this.settings.labels.allowIntersection
                && this.settings.labels.show
                && Object.keys(this.data.nodes).length <= ForceGraph.NoAnimationLimit) {
                this.nodes
                    .classed("hiddenLabel", (node: ForceGraphNode) => {
                        properties.text = this.data.formatter.format(node.name);
                        let curNodeTextRect: ITextRect = this.getTextRect(properties, node.x, node.y);

                        node.hideLabel = false;
                        this.nodes.each((otherNode: ForceGraphNode) => {
                            properties.text = this.data.formatter.format(otherNode.name);
                            let otherNodeTextRect: ITextRect = this.getTextRect(properties, otherNode.x, otherNode.y);
                            if (!otherNode.hideLabel && node.name !== otherNode.name && this.isIntersect(curNodeTextRect, otherNodeTextRect)) {
                                node.hideLabel = true;
                                return;
                            }
                        });

                        return node.hideLabel;
                    });
            }

        };
    }