diff --git a/packages-user/client-modules/src/render/map/extension/text.ts b/packages-user/client-modules/src/render/map/extension/text.ts new file mode 100644 index 0000000..a73d5aa --- /dev/null +++ b/packages-user/client-modules/src/render/map/extension/text.ts @@ -0,0 +1,63 @@ +import { IMapRenderer } from '../types'; +import { IMapTextArea, IMapTextRenderable, IOnMapTextRenderer } from './types'; + +export class OnMapTextRenderer implements IOnMapTextRenderer { + /** 画布元素 */ + readonly canvas: HTMLCanvasElement; + /** 画布 Canvas2D 上下文 */ + readonly ctx: CanvasRenderingContext2D; + + /** 图块索引到图块文本对象的映射 */ + readonly areaMap: Map = new Map(); + private dirty: boolean = false; + + constructor(readonly renderer: IMapRenderer) { + this.canvas = document.createElement('canvas'); + this.ctx = this.canvas.getContext('2d')!; + } + + render(): HTMLCanvasElement { + return this.canvas; + } + + requireBlockArea(x: number, y: number): Readonly { + const index = y * this.renderer.mapWidth + x; + const exist = this.areaMap.get(index); + if (exist) return exist; + const area = new MapTextArea(this, x, y); + this.areaMap.set(index, area); + return area; + } + + needUpdate(): boolean { + return this.dirty; + } + + clear(): void {} + + destroy(): void {} +} + +class MapTextArea implements IMapTextArea { + index: number; + + constructor( + readonly renderer: OnMapTextRenderer, + public mapX: number, + public mapY: number + ) { + this.index = mapY * renderer.renderer.mapWidth + mapX; + } + + addTextRenderable(renderable: IMapTextRenderable): void { + throw new Error('Method not implemented.'); + } + + removeTextRenderable(renderable: IMapTextRenderable): void { + throw new Error('Method not implemented.'); + } + + clear(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/packages-user/client-modules/src/render/map/extension/types.ts b/packages-user/client-modules/src/render/map/extension/types.ts index c3250fd..4617b77 100644 --- a/packages-user/client-modules/src/render/map/extension/types.ts +++ b/packages-user/client-modules/src/render/map/extension/types.ts @@ -5,6 +5,7 @@ import { IHeroState, IMapLayer } from '@user/data-state'; +import { Font } from '@motajs/render-style'; export interface IMapExtensionManager { /** @@ -79,10 +80,9 @@ export interface IMapHeroRenderer { waitMoveEnd(waitFollower: boolean): Promise; /** - * 立刻停止移动,勇士瞬移到目标点 - * @param stopFollower 是否也立刻停止跟随者的移动,此时跟随者也会瞬移到它们应该到达的地方 + * 立刻停止移动,勇士和跟随者瞬移到目标点 */ - stopMove(stopFollower: boolean): void; + stopMove(): void; /** * 勇士朝某个方向移动 @@ -162,3 +162,85 @@ export interface IMapDoorRenderer { */ destroy(): void; } + +export interface IMapTextRenderable { + /** 文本内容 */ + readonly text: string; + /** 文本字体 */ + readonly font: Font; + /** 文本填充样式 */ + readonly fillStyle: CanvasStyle; + /** 文本描边样式 */ + readonly strokeStyle: CanvasStyle; + /** 文本横坐标,注意 {@link IMapTextArea.addTextRenderable} 的相对关系 */ + readonly px: number; + /** 文本纵坐标,注意 {@link IMapTextArea.addTextRenderable} 的相对关系 */ + readonly py: number; + /** 文本横向对齐方式 */ + readonly textAlign: CanvasTextAlign; + /** 文本纵向对齐方式 */ + readonly textBaseline: CanvasTextBaseline; +} + +export interface IMapTextRequested { + /** + * 申请更新指定的图块 + * @param blocks 需要更新数据的图块列表 + */ + requestBlocks(blocks: IMapTextArea[]): void; +} + +export interface IMapTextArea { + /** 图块在地图上的索引 */ + index: number; + /** 图块横坐标 */ + mapX: number; + /** 图块纵坐标 */ + mapY: number; + + /** + * 添加文字可渲染对象。可渲染对象的坐标相对于图块,而非地图。 + * @param renderable 可渲染对象 + */ + addTextRenderable(renderable: IMapTextRenderable): void; + + /** + * 移除指定的文字可渲染对象 + * @param renderable 可渲染对象 + */ + removeTextRenderable(renderable: IMapTextRenderable): void; + + /** + * 清除本图块的所有文字可渲染对象 + */ + clear(): void; +} + +export interface IOnMapTextRenderer { + /** + * 渲染地图文字,返回的画布就是文字画到的画布 + */ + render(): HTMLCanvasElement; + + /** + * 申请指定图块坐标的文字管理对象 + * @param x 图块横坐标 + * @param y 图块纵坐标 + */ + requireBlockArea(x: number, y: number): Readonly; + + /** + * 判断是否需要更新 + */ + needUpdate(): boolean; + + /** + * 清空所有文字内容 + */ + clear(): void; + + /** + * 摧毁这个文字渲染对象,释放相关资源 + */ + destroy(): void; +}