_redraw(hidden = false) {
    if (this.allowRedraw === true) {
      this.body.emitter.emit("initRedraw");

      this.redrawRequested = false;

      const drawLater = {
        drawExternalLabels: null,
      };

      // when the container div was hidden, this fixes it back up!
      if (
        this.canvas.frame.canvas.width === 0 ||
        this.canvas.frame.canvas.height === 0
      ) {
        this.canvas.setSize();
      }

      this.canvas.setTransform();

      const ctx = this.canvas.getContext();

      // clear the canvas
      const w = this.canvas.frame.canvas.clientWidth;
      const h = this.canvas.frame.canvas.clientHeight;
      ctx.clearRect(0, 0, w, h);

      // if the div is hidden, we stop the redraw here for performance.
      if (this.canvas.frame.clientWidth === 0) {
        return;
      }

      // set scaling and translation
      ctx.save();
      ctx.translate(this.body.view.translation.x, this.body.view.translation.y);
      ctx.scale(this.body.view.scale, this.body.view.scale);

      ctx.beginPath();
      this.body.emitter.emit("beforeDrawing", ctx);
      ctx.closePath();

      if (hidden === false) {
        if (
          (this.dragging === false ||
            (this.dragging === true &&
              this.options.hideEdgesOnDrag === false)) &&
          (this.zooming === false ||
            (this.zooming === true && this.options.hideEdgesOnZoom === false))
        ) {
          this._drawEdges(ctx);
        }
      }

      if (
        this.dragging === false ||
        (this.dragging === true && this.options.hideNodesOnDrag === false)
      ) {
        const { drawExternalLabels } = this._drawNodes(ctx, hidden);
        drawLater.drawExternalLabels = drawExternalLabels;
      }

      // draw the arrows last so they will be at the top
      if (hidden === false) {
        if (
          (this.dragging === false ||
            (this.dragging === true &&
              this.options.hideEdgesOnDrag === false)) &&
          (this.zooming === false ||
            (this.zooming === true && this.options.hideEdgesOnZoom === false))
        ) {
          this._drawArrows(ctx);
        }
      }

      if (drawLater.drawExternalLabels != null) {
        drawLater.drawExternalLabels();
      }

      if (hidden === false) {
        this._drawSelectionBox(ctx);
      }

      ctx.beginPath();
      this.body.emitter.emit("afterDrawing", ctx);
      ctx.closePath();

      // restore original scaling and translation
      ctx.restore();
      if (hidden === true) {
        ctx.clearRect(0, 0, w, h);
      }
    }
  }
Redraw the network with the current data
@param {boolean} [hidden] | Used to get the first estimate of the node sizes.
                                  Only the nodes are drawn after which they are quickly drawn over.
@private