render(frameState, target) {
    this.rendered = true;
    const viewState = frameState.viewState;
    const sources = this.getSources(frameState.extent, viewState.resolution);
    let ready = true;
    for (let i = 0, ii = sources.length; i < ii; ++i) {
      const source = sources[i];
      const sourceState = source.getState();
      if (sourceState == 'loading') {
        const onChange = () => {
          if (source.getState() == 'ready') {
            source.removeEventListener('change', onChange);
            this.changed();
          }
        };
        source.addEventListener('change', onChange);
      }
      ready = ready && sourceState == 'ready';
    }
    const canvas = this.renderSources(frameState, sources);
    if (this.getRenderer().renderComplete && ready) {
      // Fully rendered, done.
      this.renderedResolution_ = viewState.resolution;
      return canvas;
    }
    // Render sources from previously fully rendered frames
    if (this.renderedResolution_ > 0.5 * viewState.resolution) {
      const altSources = this.getSources(
        frameState.extent,
        this.renderedResolution_,
      ).filter((source) => !sources.includes(source));
      if (altSources.length > 0) {
        return this.renderSources(frameState, altSources);
      }
    }
    return canvas;
  }
@param {?import("../Map.js").FrameState} frameState Frame state.
@param {HTMLElement} target Target which the renderer may (but need not) use
for rendering its content.
@return {HTMLElement} The rendered element.
@override