You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EsriJS:CustomLayerView调用requestRender报错,display未设置

解决BaseLayerView2D的display/container未设置错误

核心问题原因

BaseLayerView2D的container和display是由MapView/SceneView在初始化LayerView时自动传入并初始化的,不能手动调用super.initialize()而不传递视图提供的参数;同时requestRender()必须在LayerView初始化完成(即display已存在)后调用。

正确实现步骤

1. 完善CustomLayer的createLayerView方法

自定义Layer必须实现createLayerView,作为视图创建LayerView的入口,视图会自动处理LayerView的初始化流程:

import { Layer } from "esri/layers/Layer";
import { CustomLayerView2D } from "./CustomLayerView2D";

export class CustomLayer extends Layer {
  geometry: __esri.Geometry | null = null;
  tileInfo: __esri.TileInfo;

  constructor(props?: Partial<CustomLayer>) {
    super(props);
    // 初始化tileInfo等必要属性
    this.tileInfo = props?.tileInfo ?? { /* 你的tileInfo配置 */ };
  }

  // 视图会自动调用该方法创建LayerView,并传入初始化参数
  createLayerView(view: __esri.MapView): Promise<CustomLayerView2D> {
    return Promise.resolve(new CustomLayerView2D(this));
  }
}

2. 正确实现CustomLayerView2D的initialize方法

必须接收视图传入的options参数,并调用父类的initialize来完成container和display的初始化:

import { BaseLayerView2D } from "esri/views/layers/BaseLayerView2D";
import { projection } from "esri/geometry";
import { CustomLayer } from "./CustomLayer";

export class CustomLayerView2D extends BaseLayerView2D {
  projectedGeometry: __esri.Geometry | null = null;
  needsImageUpdate: boolean = false;
  // 可选:如果需要渲染用的canvas,提前声明
  private canvas?: HTMLCanvasElement;

  constructor(layer: CustomLayer) {
    super(layer);
    // 监听layer的geometry变化,在初始化完成后处理
    this.watch("layer.geometry", this.handleGeometryChange.bind(this));
  }

  // 视图会自动调用该方法,传入包含container、view的options
  initialize(options: { container: HTMLElement; view: __esri.MapView }): void {
    // 先调用父类initialize,自动设置this.container和this.display
    super.initialize(options);

    // 在这里初始化自定义渲染元素,比如添加canvas到container
    this.canvas = document.createElement("canvas");
    this.container.appendChild(this.canvas);
    // 可以设置canvas样式,比如占满container
    this.canvas.style.width = "100%";
    this.canvas.style.height = "100%";
  }

  private handleGeometryChange(geometry: __esri.Geometry, oldGeometry: __esri.Geometry): void {
    const layer = this.layer as CustomLayer;

    if (!layer.geometry) {
      this.projectedGeometry = null;
      this.needsImageUpdate = true;
      // 确保display已初始化后再调用requestRender
      this.display && this.requestRender();
      return;
    }

    if (geometry !== oldGeometry) {
      projection.load().then(() => {
        this.projectedGeometry = projection.project(
          layer.geometry,
          layer.tileInfo.spatialReference,
          projection.getTransformation(layer.geometry.spatialReference, layer.tileInfo.spatialReference)
        );
        this.needsImageUpdate = true;
        this.display && this.requestRender();
      });
    } else {
      this.needsImageUpdate = true;
      this.display && this.requestRender();
    }
  }

  // 必须实现render方法,requestRender会触发该方法执行渲染逻辑
  render(): void {
    if (!this.needsImageUpdate || !this.projectedGeometry || !this.canvas) return;

    // 在这里编写你的自定义渲染逻辑,比如绘制projectedGeometry
    const ctx = this.canvas.getContext("2d");
    if (!ctx) return;

    // 示例:清空canvas并绘制简单图形(需根据实际geometry类型调整)
    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    // 这里替换为你的实际渲染代码,比如将projectedGeometry转换为屏幕坐标后绘制
    // ...

    this.needsImageUpdate = false;
  }
}

3. 关键注意事项

  • 不要手动调用super.initialize()而不传递视图提供的options参数,否则会导致container和display未初始化。
  • 调用requestRender()前必须确保this.display存在(即LayerView已完成初始化),可以通过判断this.display是否为真来避免报错。
  • 必须实现render方法,否则requestRender()不会执行任何渲染操作。

内容的提问来源于stack exchange,提问作者SupremeKurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:50:55