Skip to content
Cesium创建自定义提示框控件

简介

本文介绍了如何使用Cesium创建一个自定义的提示框控件,该控件可以在Cesium地图中显示自定义的提示信息。通过这个提示框控件,您可以在地图上方便地展示各种需要突出显示的信息,提供更好的用户体验。

效果

https://bu.dusays.com/2023/06/16/648bffb9b6165.png

代码详解

这段代码定义了一个名为ToolTip的类,它是一个自定义的提示框控件。在类的构造函数中,我们接受一个Viewer对象和一个可选的ToolTipOptions对象作为参数,这些参数用于配置提示框的样式和属性。

ToolTip类具有许多有用的功能和选项。它允许您设置提示框的字体大小、颜色和背景色等样式属性。您可以根据需要自定义这些属性,以使提示框与您的应用程序或地图的整体风格相匹配。

该类还提供了方法来激活和停用提示框控件。激活后,提示框将随着鼠标移动显示,并根据设置的位置偏移量进行定位。当不再需要显示提示框时,您可以轻松地停用它。

提示框控件还提供了设置显示文本的方法。您可以使用setMessage方法将需要显示的文本信息传递给提示框控件,它将在提示框中显示该文本。

另外,提示框控件还具有刷新和销毁的功能。刷新方法用于更新提示框的样式和显示内容,使其保持与最新状态一致。销毁方法用于完全清除提示框控件的实例,释放内存和资源。

javascript
import { Cartesian2, defined, DeveloperError, destroyObject } from 'cesium';
import type { Viewer } from 'cesium';

export interface ToolTipOptions {
  fontSize?: number | string;
  fontColor?: string;
  backgroundColor?: string;
  size?: Cartesian2;
  fontOffset?: Cartesian2;
  positionOffset?: Cartesian2;
}

export const defaultToolTipOptions: ToolTipOptions = {
  fontSize: 14,
  fontColor: 'rgba(255, 255, 255, 1)',
  backgroundColor: 'rgba(11, 19, 61, 0.5)',
  size: new Cartesian2(200, 30),
  fontOffset: new Cartesian2(10, 20),
  positionOffset: new Cartesian2(1, -30),
};

export class ToolTip {
  private _toolTipsDom: HTMLParagraphElement = document.createElement('p');

  private _message: string = '';

  private _options = defaultToolTipOptions;

  private _viewer: Viewer;

  private _isActivate = false;

  isInit = false;

  /**
   * 创建提示框控件
   * @param viewer 视图
   * @param options 提示框配置样式
   */
  constructor(viewer: Viewer, options?: ToolTipOptions) {
    this._viewer = viewer;

    this._options = options ?? Object.assign(defaultToolTipOptions, options);
    this.init();
  }

  get dom() {
    return this._toolTipsDom;
  }

  /**
   * 提示框的字体大小
   */
  get fontSize() {
    return this._options.fontSize;
  }

  set fontSize(value) {
    this._options.fontSize = value;
    this.refresh();
  }

  /**
   * 提示框的字体颜色
   */
  get fontColor() {
    return this._options.fontColor!;
  }

  set fontColor(value: string) {
    this._options.fontColor = value;
    this.refresh();
  }

  /**
   * 提示框的背景色
   */
  get backgroundColor() {
    return this._options.backgroundColor!;
  }

  set backgroundColor(value: string) {
    this._options.backgroundColor = value;
    this._toolTipsDom.style.backgroundColor = value;
    this.refresh();
  }

  /**
   * 提示框中的字体以左上角为原点的偏移量
   */
  get fontOffset() {
    return this._options.fontOffset;
  }

  set fontOffset(value) {
    this._options.fontOffset = value;
    this.refresh();
  }

  /**
   * 提示框的位置以左上角为原点的偏移量
   */
  get positionOffset() {
    return this._options.positionOffset;
  }

  set positionOffset(value) {
    this._options.positionOffset = value;
    this.refresh();
  }

  /**
   * 提示框的显示文本
   */
  get message() {
    return this._message;
  }

  set message(value) {
    this._message = value;
    this.refresh();
  }

  private init() {
    if (this.isInit) {
      return;
    }
    if (!defined(this._viewer)) {
      throw new DeveloperError('viewer was not created, tooltips initialization failed.');
    }
    const options = this._options;

    // 创建鼠标提示
    this._toolTipsDom.id = 'toolTips';
    this._viewer.container.append(this._toolTipsDom);

    if (this._toolTipsDom) {
      this._toolTipsDom.style.position = 'absolute';
      this._toolTipsDom.style.display = 'none';
      this._toolTipsDom.style.padding = '4px 10px';
      this._toolTipsDom.style.borderRadius = '2px';
      this._toolTipsDom.style.color = options?.fontColor!;
      this._toolTipsDom.style.backgroundColor =
        options?.backgroundColor! || defaultToolTipOptions.backgroundColor!;
      this._toolTipsDom.style.fontSize =
        `${options?.fontSize!}` || `${defaultToolTipOptions.fontSize!}px`;
    }

    this.isInit = true;
    this.setStyle(options);
  }

  /**
   * 设置控件位置
   * @param x number 控件的屏幕x坐标
   * @param y number 控件的屏幕y坐标
   */
  setTipsPosition(x: number, y: number) {
    const { positionOffset } = this._options;
    const offsetx = positionOffset && positionOffset.x ? positionOffset.x : 0;
    const offsety = positionOffset && positionOffset.y ? positionOffset.y : 0;
    this._toolTipsDom.style.top = `${y + offsety}px`;
    const isOverWidth = x + this._toolTipsDom.clientWidth + 20 < this._viewer.container.clientWidth;
    this._toolTipsDom.style.left = isOverWidth
      ? `${x + offsetx + 10}px`
      : `${x - offsetx - this._toolTipsDom.clientWidth - 10}px`;
  }

  private _mouseMoveListener(event: any) {
    this._toolTipsDom.style.display = 'block';
    this.setTipsPosition(event.offsetX, event.offsetY);
  }

  private _mouseLeaveListener() {
    this._toolTipsDom.style.display = 'none';
  }

  /**
   * 激活提示控件
   */
  activate() {
    if (this._isActivate) return;

    this._isActivate = true;
    this._toolTipsDom.style.display = 'block';
    this._mouseMoveListener = this._mouseMoveListener.bind(this);
    this._mouseLeaveListener = this._mouseLeaveListener.bind(this);
    this._viewer.canvas.addEventListener('mousemove', this._mouseMoveListener);
    this._viewer.canvas.addEventListener('mouseleave', this._mouseLeaveListener);
  }

  /**
   * 停用提示控件
   */
  deactivate() {
    if (this._isActivate) {
      this._toolTipsDom.style.display = 'none';
      this._viewer.canvas.removeEventListener('mousemove', this._mouseMoveListener);
      this._viewer.canvas.removeEventListener('mouseleave', this._mouseLeaveListener);
      this._isActivate = false;
    }
  }

  /**
   * 设置提示框得样式
   * @param options object 提示框样式
   */
  setStyle(options?: ToolTipOptions) {
    if (options) this._options = Object.assign(defaultToolTipOptions, options);

    this.refresh();
  }

  /**
   * 显示文本信息
   * @param message 需要显示得文本信息
   */
  setMessage(message: string) {
    this._toolTipsDom.innerHTML = message;
  }

  /**
   * 刷新提示框显示消息
   */
  refresh() {
    this._toolTipsDom.style.font = `${this._options.fontSize}px 微软雅黑`;
    this._toolTipsDom.style.color = this._options.fontColor!;
    if (defined(this._message)) {
      this.setMessage(this._message);
    }
  }

  /**
   * 销毁
   */
  destroy() {
    if (this._isActivate) {
      this.deactivate();
    }
    this._viewer.container.removeChild(this._toolTipsDom);

    return destroyObject(this);
  }
}

Updated at: