自定义座位状态(Renderer SDK)

自定义座位状态可在渲染器已有内容上,为单个座位添加应用定义的视觉标记,例如 reserved、held、vip 或 sold。状态是字符串键:运行时通过 setSeatsState 将键分配给座位集合,并在 theme.seatStyles 中定义其外观。

本指南介绍客户端 SDK(@seatmap.pro/renderer)如何在浏览器中应用和展示状态。后端座位生命周期与客户定义的保留类型,即 Booking 服务的 state / holdType 模型,请参阅座位状态与保留类型,两者相互补充。

概览

该功能由两个独立层组成,区分它们是正确使用 API 的关键。

层 控制内容 使用方式
分配引擎 哪些座位处于何种状态 setSeatsState(seats, key) / clearSeatsState(seats)
样式配置 状态键的外观 theme.seatStyles,构造时声明

分配引擎维护座位 ID 到单个状态键的映射,每座位最多一个键,不涉及颜色、大小或 DOM。样式配置将状态键映射为样式描述,位于构造时传入的设置中,状态方法不会在运行时修改它。

只有同时满足两个条件才显示覆盖层:引擎已为座位分配键,且 seatStyles 存在该键对应条目。

覆盖层属于 DOM 层

屏幕上显示的是 DOM 覆盖层:渲染器宿主元素内追加一个绝对定位的 <div> 容器,每个可见且有状态的座位对应一个小 <div>。它不绘制到 WebGL 或 Canvas2D 舞台。由于只读取共享视口变换(scale / translate),两条渲染路径行为相同。容器使用 pointer-events: none,不会截获画布输入。

快速开始

最小完整流程:在 theme.seatStyles 中定义一个自定义状态,构造渲染器并加载活动,待座位存在后为其分配状态。

import { SeatmapBookingRenderer } from '@seatmap.pro/renderer';

const element = document.getElementById('seatmap') as HTMLElement;

const renderer = new SeatmapBookingRenderer(element, {
  publicKey: 'your-public-key',
  theme: {
    seatStyles: {
      mykey: {
        tint: 'rgba(76,141,255,0.5)',
        keepSeatName: true,
      },
    },
  },
});

void renderer.loadEvent('event-guid').then(() => {
  renderer.setSeatsState([101, 102, 103], 'mykey');
});

注意:

  • SeatmapBookingRenderer 运行时必须有 publicKey,缺失时构造器抛出 'Public key is undefined'。
  • 必须在座位已存在之后调用 setSeatsState,即 loadEvent 完成后,或在 onSchemaDataLoaded 中调用。状态仅应用于已加载座位。
  • 在完整场地缩放下覆盖节点很小。用 zoomToSection 放大区域可清楚查看,见下文示例。

概念

分配引擎语义

  • 每座位一个状态:每个座位恰有一个分配键,或没有。
  • 覆盖而非合并:分配新状态会替换旧状态。先设 reserved 再设 sold,最终为 sold。
  • 按座位清除,忽略未命中:清除未分配 ID 时直接跳过,局部清除不影响其他座位。
  • 阻止交互单独判断:只有座位已分配状态,且该键样式的 blockInteraction 为真值,才视为阻止。状态本身不意味着禁止交互。

内置键与自定义键

内置键是渲染器自身状态,由 BuiltinSeatStateKey 枚举:

type BuiltinSeatStateKey =
  | 'default'
  | 'unavailable'
  | 'filtered'
  | 'hovered'
  | 'selected'
  | 'loading'
  | 'error';

它们使用更丰富的 ISeatStyle,包含大小、颜色、描边、阴影及无障碍覆盖。预置 booking 和 admin 主题已定义这些状态。特别地,default 条目的 size 决定所有覆盖节点的尺寸,见性能与渲染说明。

自定义键可以是其他任意字符串,如 'reserved'、'held'、'vip'、'sold'、'restricted'。通过 setSeatsState 分配,以轻量 ICustomSeatStyle 或完整 ISeatStyle 设置样式。

样式配置

所有座位样式位于类型为 SeatStylesMap 的 theme.seatStyles 中。

SeatStylesMap 结构

type SeatStylesMap = Partial<Record<BuiltinSeatStateKey, ISeatStyle>> & {
  [customKey: string]: ICustomSeatStyle | ISeatStyle | undefined;
};
  • Partial<Record<BuiltinSeatStateKey, ISeatStyle>> 将七个内置键约束为含 accessible 覆盖的 ISeatStyle,七个键均可选。
  • 索引签名允许任意字符串键,值为轻量 ICustomSeatStyle 或完整 ISeatStyle。将 Partial<Record<...>> 与通用索引签名组合时,TypeScript 要求联合类型包含 undefined。

实践中,内置键使用 ISeatStyle,自定义键通常使用 ICustomSeatStyle。

IBasicSeatStyle

interface IBasicSeatStyle {
  size: number;
  color: string;
  seatName?: {
    font: string;
    color: string;
  };
  stroke?: {
    width: number;
    color: string;
    align: 'center' | 'inside' | 'outside';
  };
  imageId?: string;
  shadow?: {
    blur: number;
    color: string;
    x?: number;
    y?: number;
  };
}
字段 类型 可选 含义
size number 否 渲染尺寸,按渲染器单位表示直径或半径。
color string 否 座位填充色。
seatName { font: string; color: string } 是 标签排版;font 为 CSS 字体字符串,如 '18px Arial',color 为文字颜色。
stroke { width: number; color: string; align: 'center' | 'inside' | 'outside' } 是 边框粗细、颜色及相对座位边缘的对齐方式。
imageId string 是 预注册图片素材 ID。
shadow { blur: number; color: string; x?: number; y?: number } 是 阴影模糊半径、颜色及可选 X/Y 偏移。

ISeatStyle

interface ISeatStyle extends IBasicSeatStyle {
  accessible?: IBasicSeatStyle;
}
字段 类型 可选 含义
继承全部 IBasicSeatStyle 字段 见上表。
accessible IBasicSeatStyle 是 座位标为无障碍或轮椅座位时使用的覆盖样式,含相同六个基础字段,不含 accessible 自身。

ICustomSeatStyle

interface ICustomSeatStyle {
  tint?: string;
  svg?: string;
  imageId?: string;
  className?: string;
  priority?: number;
  blockInteraction?: boolean;
  keepSeatName?: boolean;
  render?: (args: ISeatStateRenderArgs) => HTMLElement | string;
}
字段 类型 可选 含义
tint string 是 在座位范围内覆盖颜色,以实心圆绘制。
svg string 是 以 < 开头时视为内联 SVG,否则作为 URL。
imageId string 是 从 theme.images[imageId] 查找的预注册素材 ID。
className string 是 添加到覆盖层 div 的 CSS 类,用于样式或动画。
priority number 是 类型接受此值,但覆盖层当前不读取;没有 z 顺序,设置无效。
blockInteraction boolean 是 为 true 时报告座位被阻止,见阻止交互。
keepSeatName boolean 是 默认显示覆盖节点上的座位标签,只有 false 才隐藏。
render (args: ISeatStateRenderArgs) => HTMLElement | string 是 完全提供覆盖内容的自定义 DOM 回调。

ICustomSeatStyle 没有自己的 size。覆盖节点共享默认座位尺寸,来自 seatStyles['default']?.size,不存在时回退为 10。

ISeatStateRenderArgs

自定义 render 回调接收的唯一参数:

interface ISeatStateRenderArgs {
  seat: ISeat;
  stateKey: string;
  style: ICustomSeatStyle;
  sizePx: number;
}
字段 类型 含义
seat ISeat 正在渲染的完整座位对象。
stateKey string 触发本次渲染的内置或自定义状态键。
style ICustomSeatStyle 已解析样式,供回调检查自身配置。
sizePx number 座位当前像素尺寸,供回调缩放输出。

公共 API

两个方法均定义在基础渲染器上,SeatmapBookingRenderer 和 SeatmapAdminRenderer 一致提供。仅在活动及座位加载后应用状态。

setSeatsState

setSeatsState(seats: ISeat[] | number[] | string[], stateKey: string): void

解析座位 ID,将 stateKey 记录到引擎并覆盖旧状态,为每个匹配座位对象写入 customState,然后重绘以同步覆盖层。seats 为空时不执行操作。

clearSeatsState

clearSeatsState(seats: ISeat[] | number[] | string[]): void

解析 ID,清除引擎分配(未命中则跳过),删除匹配座位对象的 customState,然后重绘。seats 为空时不执行操作。

参数形式

两个方法的 seats 接受相同联合类型:

  • ISeat[]:通过 .id 解析的座位对象。
  • number[]:数字座位 ID。
  • string[]:内部解析为 ID 的组合座位键。

方法根据第一个元素的类型决定 ID 解析方式。

清除全部座位

没有无参数“清除全部”重载。请通过 getSeats 显式传入所有座位 ID:

renderer.clearSeatsState(renderer.getSeats().map((s) => s.id));

定义自定义状态

自定义状态是 seatStyles 下任意键对应的条目,可组合以下字段:

  • 着色:tint 在座位范围覆盖 CSS 颜色的实心圆;内置 ISeatStyle 的 color 为座位填充色。
  • 大小:无独立尺寸,使用 seatStyles['default']?.size,回退 10;ISeatStateRenderArgs.sizePx 返回解析值。
  • 描边:IBasicSeatStyle / ISeatStyle 提供 width、color、align;需要时使用完整 ISeatStyle。
  • 阴影:基础或完整样式提供 blur、color、x、y。
  • 座位名称 / keepSeatName:默认显示标签,设 false 隐藏;seatName 字体和颜色属于内置样式。
  • className:给覆盖 div 添加类,以便从样式表设置外观或动画。
  • imageId:绘制 theme.images[imageId] 解析出的预注册素材。
  • priority:已声明但当前不使用。每座位最多一个自定义状态,无 z 顺序,设置无效果。
  • blockInteraction:通过阻止交互检查提供结果,见阻止交互。

示例:

const seatStyles: SeatStylesMap = {
  restricted: {
    tint: 'rgba(214,88,78,0.6)',
    blockInteraction: true,
    keepSeatName: false,
  },
  promo: {
    tint: 'rgba(76,141,255,0.5)',
    className: 'promo-seat',
  },
};

覆盖内置座位状态

同一 theme.seatStyles 也可覆盖内置状态。内置键修改的是画布舞台上的座位图形,由渲染器根据锁定、过滤、悬停、选中等实际条件自动应用,无需调用 setSeatsState。

内置键 应用条件
default 可用,未悬停或选中
unavailable 已锁定或不可售
filtered 从当前视图中过滤
hovered 指针所在且可交互
selected 已选中或在购物车中
loading 加载中
error 错误状态

构造时,您的 seatStyles 会深度合并到预置默认主题上,因此可只覆盖单个字段并继承其他值。例如将选中座位放大、设为绿色并加粗边框,同时调整不可用座位颜色:

const renderer = new SeatmapBookingRenderer(element, {
  publicKey: 'your-public-key',
  theme: {
    seatStyles: {
      selected: {
        size: 46,
        color: '#1f9d55',
        stroke: { width: 3, color: '#0b5d2e', align: 'outside' },
      },
      unavailable: { size: 8, color: '#d0d0d0' },
    },
  },
});

注意:

  • 内置键接受 ISeatStyle 的 size、color、seatName、stroke、imageId、shadow、accessible;只提供要更改的字段即可。
  • 这控制画布座位图形,与 DOM 自定义覆盖层独立。座位可在画布上显示 selected,同时叠加自定义状态。
  • default.size 同时控制基础座位和所有自定义覆盖节点的尺寸,见性能与渲染说明。

示例方案:同时显示票价颜色、状态图片和座位号

常见需求是按票价档位着色,同时叠加 reserved、held、sold 等交易状态图标或 SVG 遮罩,并保留清晰的座位号。只用一个画布图形会产生冲突:

  1. 通过样式 imageId 或 onBeforeSeatDraw 直接绘制图片,会替换整个座位图形。绘制路径在图片完成后立即返回,不再绘制编号。
  2. 图片本身就是座位图形,按图片自身像素尺寸绘制,不易恰好填满座位圆。
  3. onBeforeSeatDraw 返回新的 ISeatStyle 会替换完整样式,丢失 setSeatsCategory 设置的票价或类别颜色。

自定义状态是绘制在画布上方的独立 DOM 层,可避免以上问题:

  • 保留票价颜色:setSeatsState 不修改 seat.special.category 或类别颜色映射。
  • 图片填满座位:svg / imageId 使用完整座位范围,inset: 0,宽高等于默认座位尺寸。
  • 编号保持在顶层:默认在图片上居中重绘座位号;仅希望图标替代编号时才设 keepSeatName: false,如 sold 的锁图标。

用两个独立、可组合的调用替代逐座位 onBeforeSeatDraw:

// 1) Price-tier color, painted on the canvas seat -- persists.
renderer.setSeatsCategory(seatIds, priceCategoryId, '#1f9d55');

// 2) Transactional state overlay on top -- seat number preserved.
renderer.setSeatsState(seatIds, 'reserved');

构造时定义一次状态。省略 tint,让票价颜色透过遮罩透明部分显示:

const seatStyles: SeatStylesMap = {
  reserved: {
    keepSeatName: true, // default -- seat number stays visible on top
    svg:
      '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">' +
      '<circle cx="50" cy="50" r="42" fill="none" stroke="#fff" stroke-width="6"/></svg>',
  },
};

这样保留票价颜色,SVG 作为覆盖遮罩填满座位,编号绘制在顶层,无需 onBeforeSeatDraw。要改变状态颜色,可添加半透明 tint。要使用命名素材而非内联 SVG,在 theme.images 注册并通过 imageId 引用:

const renderer = new SeatmapBookingRenderer(element, {
  publicKey: 'your-public-key',
  theme: {
    images: { holdIcon: 'data:image/svg+xml;utf8,...' }, // or a URL
    seatStyles: {
      held: { imageId: 'holdIcon', keepSeatName: true },
    },
  },
});

完整场地缩放下覆盖层很小,详细单区域视图中会隐藏。状态未显示时参阅性能与渲染说明。每个状态座位都是独立 DOM 节点,因此需限制同时可见数量;它们不像画布座位那样批量绘制,大量节点会降低性能。

通过 render() 自定义 DOM

声明式字段不足时,可提供 render 回调,完全生成该状态节点的内容:

render?: (args: ISeatStateRenderArgs) => HTMLElement | string;

回调接收 ISeatStateRenderArgs(seat、stateKey、style、sizePx),返回:

  • HTMLElement:直接追加到覆盖节点,可用于复杂或交互内容。
  • string:作为原始 SVG 标记,包在绝对定位的 div(inset: 0)中,通过填满节点的 <img src="data:image/svg+xml;utf8,..."> 渲染。

存在 render 时,它接管内容生成,不再使用该状态的 tint / svg / imageId 声明式路径。动态、数据驱动的视觉效果适合回调,例如依据 seat 或 sizePx 绘图;静态效果优先使用更简单、无需回调的声明式字段。

const seatStyles: SeatStylesMap = {
  badge: {
    render: ({ sizePx }: ISeatStateRenderArgs): string =>
      `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${sizePx} ${sizePx}">` +
      `<circle cx="${sizePx / 2}" cy="${sizePx / 2}" r="${sizePx / 3}" fill="#fff"/></svg>`,
  },
};

动画

有两种实现路径。

SVG 内置动画(SMIL)

示例状态直接在 SVG 字符串中使用 <animate>、<animateTransform>,无需外部 CSS、@keyframes 或 className。例如对圆的 r 和 stroke-opacity 动画产生脉冲环。下文完整示例采用此方式。

通过 className 使用 CSS 动画

在状态中设置 className,覆盖 div 获得该类,再从自己的样式表应用动画:

.promo-seat {
  animation: promo-pulse 1.4s ease-in-out infinite;
}

@keyframes promo-pulse {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
}
const seatStyles: SeatStylesMap = {
  promo: { tint: 'rgba(76,141,255,0.5)', className: 'promo-seat' },
};

阻止交互

只有同时满足以下条件,座位才报告为被阻止:

  1. 已分配状态键。
  2. seatStyles[stateKey] 存在,且 blockInteraction 为真值。

因此,无状态分配、样式缺少 blockInteraction 或其为假值、以及没有 seatStyles 映射时,都不会被阻止。

例如 { sold: { blockInteraction: true }, held: { tint: '#4c8dff' } } 中,sold 座位被阻止,held 座位不被阻止。

keepSeatName 与阻止交互独立。标签默认显示,仅 false 隐藏。下文 sold 用 false 让锁图标替代编号,reserved、held 和 vip 使用 true。

Booking 与 Admin Renderer

setSeatsState 和 clearSeatsState 定义在基础渲染器中,两种渲染器原样继承,API、参数形式和行为一致,仅构造设置类型不同。

SeatmapBookingRenderer:

constructor(
  element: HTMLElement,
  settings?: IBookingRendererSettings,
  tags?: Record<string, string | number | boolean>,
)

SeatmapAdminRenderer:

constructor(element: HTMLElement, settings?: IAdminRendererSettings)

两种设置均接受 settings.theme.seatStyles。

为什么演示使用 Admin Renderer

Admin Renderer 更便于直观验证状态,这是显示效果的区别,而非 API 能力区别。Booking Renderer 根据真实活动可用性绘制座位,实际不可用的演示座位会显示 unavailable 样式,可能遮盖自定义覆盖层。Admin Renderer 不应用这类预订可用性样式,因此状态更清晰。生产中,Booking Renderer 为真正可用的座位提供完全相同的方法。

完整示例

以下示例提供四种典型状态及完整流程,可直接复制使用。

theme.seatStyles 中的四种状态

const seatStyles: SeatStylesMap = {
  reserved: {
    tint: 'rgba(224,161,60,0.55)',
    keepSeatName: true,
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="none" stroke="#fff" stroke-width="6"><animate attributeName="r" values="34;46;34" dur="1.4s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.9;0.3;0.9" dur="1.4s" repeatCount="indefinite"/></circle></svg>',
  },
  held: {
    tint: 'rgba(76,141,255,0.5)',
    keepSeatName: true,
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="42" fill="none" stroke="#fff" stroke-width="5"><animate attributeName="stroke-opacity" values="0.15;0.85;0.15" dur="2.2s" repeatCount="indefinite"/></circle></svg>',
  },
  vip: {
    tint: 'rgba(155,108,255,0.5)',
    keepSeatName: true,
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="none" stroke="#fff" stroke-width="5" stroke-dasharray="30 200" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" dur="2.4s" repeatCount="indefinite"/></circle></svg>',
  },
  sold: {
    tint: 'rgba(214,88,78,0.6)',
    blockInteraction: true,
    keepSeatName: false,
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#fff" d="M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5m0 2a3 3 0 0 1 3 3v3H9V6a3 3 0 0 1 3-3"/></svg>',
  },
};

各状态概要:

  • reserved:tint、keepSeatName true,1.4 秒脉冲环,SMIL 改变 r 和 stroke-opacity。
  • held:tint、keepSeatName true,2.2 秒渐隐环,SMIL 改变 stroke-opacity。
  • vip:tint、keepSeatName true,2.4 秒旋转虚线环,SMIL animateTransform rotate。
  • sold:tint、blockInteraction true、keepSeatName false,静态锁图标,无动画。

四种状态均未使用 color、size、stroke、render 或 className。

选择演示区域

按区域分组座位,返回第一个至少有 44 个座位的区域;否则返回最大的区域:

const pickCustomStateDemoSection = (
  renderer: SeatmapAdminRenderer,
): { sectionId: number; ids: number[] } => {
  const bySection = new Map<number, number[]>();
  for (const seat of renderer.getSeats()) {
    const list = bySection.get(seat.sectorId) ?? [];
    list.push(seat.id);
    bySection.set(seat.sectorId, list);
  }
  let best: { sectionId: number; ids: number[] } | null = null;
  for (const [sectionId, ids] of bySection) {
    if (ids.length >= 44) return { sectionId, ids };
    if (!best || ids.length > best.ids.length) best = { sectionId, ids };
  }
  return best ?? { sectionId: 0, ids: [] };
};

混合演示流程

先清除所有座位状态,再为演示区域的不重叠片段应用四种状态,最后放大:

const demoMix = (renderer: SeatmapAdminRenderer): void => {
  const { sectionId, ids } = pickCustomStateDemoSection(renderer);
  const pick = (from: number, to: number): number[] => ids.slice(from, to);
  renderer.clearSeatsState(renderer.getSeats().map((s) => s.id));
  renderer.setSeatsState(pick(0, 12), 'reserved');
  renderer.setSeatsState(pick(12, 24), 'held');
  renderer.setSeatsState(pick(24, 32), 'vip');
  renderer.setSeatsState(pick(32, 44), 'sold');
  renderer.zoomToSection(sectionId, { focus: true });
};

zoomToSection(sectionId, { focus: true }) 使小型覆盖节点清晰可见。

单状态操作

不先清除,为对应片段应用一个状态,再放大:

const applyReserved = (renderer: SeatmapAdminRenderer): void => {
  const { sectionId, ids } = pickCustomStateDemoSection(renderer);
  renderer.setSeatsState(ids.slice(0, 12), 'reserved');
  renderer.zoomToSection(sectionId, { focus: true });
};

held、vip、sold 操作形式相同,分别使用 ids.slice(12, 24)、ids.slice(24, 32)、ids.slice(32, 44)。

清除所有状态

const clearStates = (renderer: SeatmapAdminRenderer): void => {
  const ids = renderer.getSeats().map((s) => s.id);
  renderer.clearSeatsState(ids);
};

性能与渲染说明

覆盖层的 DOM 成本与实际屏幕内容成比例,但它是真实 DOM,性能取决于同时可见的状态座位数。

  • 限制可见状态座位数量:每个座位创建独立 div,SVG 或图片增加 img,可选 tint 层及座位号节点。与 WebGL 座位层不同,节点不批量绘制,每个 SMIL SVG 也独立运行动画。少量到几十个通常可行;同时显示数百或数千个会显著降低帧率,动画更甚。全场地样式优先使用画布批量路径,如 setSeatsCategory 票价或类别颜色,以及 seatStyles 的内置状态覆盖。自定义覆盖层适合用户正在查看的有限座位;数量较多时优先静态效果。
  • 虚拟化:只为可见集合与已分配集合交集中的座位创建节点。视口外不创建,滚出视口即移除。
  • 延迟创建容器:至少分配一个状态后才创建容器;没有剩余状态时,清除全部节点并移除容器。
  • 详细区域视图隐藏:进入详细单区域视图时,覆盖层 display: none,跳过同步;离开后恢复。这与区域详情视图有关,与 3D 模式无关。
  • 完整场地缩放下很小:尺寸来自 seatStyles['default']?.size,回退 10;节点使用世界坐标并随视口变换缩放。因此示例调用 zoomToSection 放大。
  • 独立于舞台:只读取视口变换、宿主元素、devicePixelRatio 和用于解析 imageId 的 theme.images,在 WebGL 与 Canvas2D 回退中行为相同。

故障排查

覆盖层不可见:

  • 缩放过小:调用 zoomToSection(sectionId, { focus: true }) 或其他方式放大。
  • 详细单区域视图会隐藏覆盖容器,退出后恢复;3D 旋转不会隐藏。
  • 座位尚未加载:在 loadEvent 完成后或 onSchemaDataLoaded 中应用状态。
  • 键错误或未配置样式:传入键必须与 theme.seatStyles 条目完全一致。

状态未清除:

  • clearSeatsState 只清除传入 ID,未命中会跳过。清除全部使用 renderer.clearSeatsState(renderer.getSeats().map((s) => s.id))。最后一个状态移除后,整个覆盖容器会从 DOM 删除。

Booking Renderer 演示座位显示不可用:

  • 真实活动不可用样式可能遮盖覆盖层。演示可使用不应用该样式的 SeatmapAdminRenderer;生产 Booking Renderer 应对真正可用的座位应用状态。

API 速查

符号 签名或结构 位置
setSeatsState (seats: ISeat[] | number[] | string[], stateKey: string): void Renderer,booking 与 admin
clearSeatsState (seats: ISeat[] | number[] | string[]): void Renderer,booking 与 admin
setSeatsCategory (seats: ISeat[] | number[] | string[], category: number, color?: string): void Renderer,booking 与 admin
getSeats () => ISeatDTO[],用于列举全部座位以清除 Renderer
zoomToSection (sectionId, { focus: true }) Renderer
loadEvent booking:(eventId: string, sectorId?: number) => Promise<void>;admin:(eventId: string) => Promise<void> 渲染器
BuiltinSeatStateKey 'default' | 'unavailable' | 'filtered' | 'hovered' | 'selected' | 'loading' | 'error' 类型
SeatStylesMap Partial<Record<BuiltinSeatStateKey, ISeatStyle>> & { [customKey: string]: ICustomSeatStyle | ISeatStyle | undefined } 类型
IBasicSeatStyle { size; color; seatName?; stroke?; imageId?; shadow? } 接口
ISeatStyle IBasicSeatStyle & { accessible?: IBasicSeatStyle } 接口
ICustomSeatStyle { tint?; svg?; imageId?; className?; priority?; blockInteraction?; keepSeatName?; render? } 接口
ISeatStateRenderArgs { seat: ISeat; stateKey: string; style: ICustomSeatStyle; sizePx: number } 接口
IRendererTheme.seatStyles seatStyles?: SeatStylesMap 主题字段
IRendererTheme.images images?: { [id: string]: string },通过 imageId 解析命名素材 主题字段
  • 座位状态与保留类型:后端生命周期和 state / holdType 数据模型,介绍服务器端转换;本页介绍客户端可视化。
  • 区域状态与样式:区域轮廓的高亮、选中、不可用和过滤。
  • 初始化 SDK:安装包、构造渲染器并加载活动后,再应用自定义状态。

输入功能、设置、端点或 SDK 方法。