animateView(options) {
    if (options === undefined) {
      return;
    }
    this.animationEasingFunction = options.animation.easingFunction;
    // release if something focussed on the node
    this.releaseNode();
    if (options.locked === true) {
      this.lockedOnNodeId = options.lockedOnNode;
      this.lockedOnNodeOffset = options.offset;
    }

    // forcefully complete the old animation if it was still running
    if (this.easingTime != 0) {
      this._transitionRedraw(true); // by setting easingtime to 1, we finish the animation.
    }

    this.sourceScale = this.body.view.scale;
    this.sourceTranslation = this.body.view.translation;
    this.targetScale = options.scale;

    // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw
    // but at least then we'll have the target transition
    this.body.view.scale = this.targetScale;
    const viewCenter = this.canvas.DOMtoCanvas({
      x: 0.5 * this.canvas.frame.canvas.clientWidth,
      y: 0.5 * this.canvas.frame.canvas.clientHeight,
    });

    const distanceFromCenter = {
      // offset from view, distance view has to change by these x and y to center the node
      x: viewCenter.x - options.position.x,
      y: viewCenter.y - options.position.y,
    };
    this.targetTranslation = {
      x:
        this.sourceTranslation.x +
        distanceFromCenter.x * this.targetScale +
        options.offset.x,
      y:
        this.sourceTranslation.y +
        distanceFromCenter.y * this.targetScale +
        options.offset.y,
    };

    // if the time is set to 0, don't do an animation
    if (options.animation.duration === 0) {
      if (this.lockedOnNodeId != undefined) {
        this.viewFunction = this._lockedRedraw.bind(this);
        this.body.emitter.on("initRedraw", this.viewFunction);
      } else {
        this.body.view.scale = this.targetScale;
        this.body.view.translation = this.targetTranslation;
        this.body.emitter.emit("_requestRedraw");
      }
    } else {
      this.animationSpeed =
        1 / (60 * options.animation.duration * 0.001) || 1 / 60; // 60 for 60 seconds, 0.001 for milli's
      this.animationEasingFunction = options.animation.easingFunction;

      this.viewFunction = this._transitionRedraw.bind(this);
      this.body.emitter.on("initRedraw", this.viewFunction);
      this.body.emitter.emit("_startRendering");
    }
  }
@param {object} options  |  options.offset   = {x:number, y:number}   // offset from the center in DOM pixels
                         |  options.time     = number                 // animation time in milliseconds
                         |  options.scale    = number                 // scale to animate to
                         |  options.position = {x:number, y:number}   // position to animate to
                         |  options.easingFunction = String           // linear, easeInQuad, easeOutQuad, easeInOutQuad,
                                                                      // easeInCubic, easeOutCubic, easeInOutCubic,
                                                                      // easeInQuart, easeOutQuart, easeInOutQuart,
                                                                      // easeInQuint, easeOutQuint, easeInOutQuint