跳到主要内容

使用 Kaleidr 底图

完成本指南后,您的网页将显示一张具有指定样式和相机视角的交互式 Kaleidr 底图,代码还能移动相机或切换样式。所有套餐(包括 Free)均可使用。您需要一个具备 maps 权限范围的可公开使用的密钥,新建密钥默认包含该权限。

开始之前​

  • 从 kaleidr.com/api-keys 获取可公开使用的密钥(kld_pk_live_…)。参阅获取 API 密钥。
  • 测试网页的来源(如 http://localhost:3000)必须在密钥的允许来源列表中。如果密钥未限制来源,则可以在任何网站使用。
  • 通过 HTTP 提供网页的工具,例如 npx serve .。直接从磁盘打开的网页没有可用来源,因此会被限制来源的密钥拒绝。
  • 如果网站设置了内容安全策略,请在 script-src 中允许 https://cdn.kaleidr.com,在 connect-src 中允许 https://api.kaleidr.com,在 frame-src 中允许 https://map-embed.kaleidr.com。参阅内容安全策略。

第 1 步:添加地图​

<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<kaleidr-map product="tile"
publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
style="display:block; height:480px"></kaleidr-map>

**预期结果:**先出现“Loading map…”提示,随后显示明亮的底图。在 Network 面板中,向 https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions 发送的 POST 请求返回 200,随后向 https://map-embed.kaleidr.com/ 请求文档。iframe URL 仅包含样式 ID,不包含凭据:密钥只用于会话请求,会话令牌不会出现在 iframe URL 中。

元素必须设置高度,否则地图会采用固定的 500 像素高度。<kaleidr-map> 默认使用 display:block,因此高度会生效。仍建议显式写入 display:block,以兼容 Safari 16.4 之前的版本;旧版本中该元素以行内方式显示,并忽略 height。

第 2 步:选择样式​

将 style-id 设置为以下通用样式之一:

style-id外观
kaleidr-morning明亮:白色地面、青色水域、白色道路。
kaleidr-afternoon中等色调的地面、绿色植被和灰色道路。
kaleidr-evening黄金时刻:暖沙色和橄榄色调。
kaleidr-night深海军蓝和炭灰色,主干道呈琥珀色。
kaleidr-plain白色画布,保留边界与地点标签;缩放级别达到 15 后显示 3D 建筑。
kaleidr-editorial不显示标签的午后配色,适合小型或装饰性地图。
<kaleidr-map product="tile" publishable-key="kld_pk_live_…"
style-id="kaleidr-night"
style="display:block; height:480px"></kaleidr-map>

**预期结果:**同一地图区域改用深色配色。

请始终传入 style-id。如果省略,将使用组织设置的默认底图;如果未设置默认底图,iframe 会显示“Couldn't find a map id in the URL.”。

样式 ID 必须完全匹配,不支持短别名。例如 night 不能代替 kaleidr-night。

第 3 步:设置相机​

如果未指定相机,地图会使用样式的默认视角,通常显示整个世界。传入 center(先经度、后纬度)和 zoom 可定位到目标区域。pitch 控制倾斜角,bearing 控制旋转方向。

<kaleidr-map product="tile" publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
center="-0.1276,51.5072" zoom="12" pitch="45" bearing="-20"
style="display:block; height:480px"></kaleidr-map>

**预期结果:**倾斜、旋转的伦敦市中心地图。

如果没有同时传入 center,系统会忽略 zoom。 pitch 和 bearing 可以单独设置。

第 4 步:通过代码移动相机并切换样式​

元素写法属于声明式集成。若要从 JavaScript 控制地图,请调用 Kaleidr.mount 并保留返回的控制句柄。

<div id="basemap" style="height:480px"></div>
<p>
<button id="paris">Fly to Paris</button>
<button id="night">Night</button>
<button id="day">Morning</button>
</p>

<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<script>
const handle = Kaleidr.mount('#basemap', {
product: 'tile',
publishableKey: 'kld_pk_live_…',
styleId: 'kaleidr-morning',
center: [-0.1276, 51.5072],
zoom: 11,
});

document.getElementById('paris').addEventListener('click', () => {
// duration is in milliseconds. Leave it out to jump with no animation.
handle.setCamera({ center: [2.3522, 48.8566], zoom: 12, duration: 1200 });
});
document.getElementById('night').addEventListener('click', () => {
handle.setStyle('kaleidr-night');
});
document.getElementById('day').addEventListener('click', () => {
handle.setStyle('kaleidr-morning');
});
</script>

**预期结果:**每个按钮都在原位置更新地图,iframe 不会重新加载,Network 面板也不会新增会话请求。

注意以下事项:

  • setCamera 和 setStyle 属于控制句柄,而非元素本身。
  • setStyle 仅支持 Tile。对其他产品调用时只会打印警告,不执行操作。
  • Kaleidr.mount 返回后,可以随时调用句柄方法。若 iframe 中的地图尚未就绪,调用会按顺序排队,在地图就绪时应用,因此无需等待第 6 步的 kaleidr-embed:ready 消息。初始相机和样式应通过挂载选项设置。
  • 对已挂载的元素修改 center、zoom、pitch 或 bearing 可以移动地图,但修改 style-id 不会产生效果。

第 5 步:将聊天面板连接到地图(可选)​

Kaleidr Chat 面板可以将 Tile 地图作为目标,在地图上为回答中的地点绘制标记,并调整相机使其进入视野。将 Tile 元素放入定位容器中,在其上叠加聊天元素,并通过 map-target 指向 Tile 元素。

<div style="position:relative">
<kaleidr-map id="basemap" product="tile"
publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
center="-0.1276,51.5072" zoom="11"
style="display:block; height:560px"></kaleidr-map>

<kaleidr-map product="chat" publishable-key="kld_pk_live_…" contained
map-target="#basemap"
style="display:block; position:absolute; inset:0; z-index:1; pointer-events:none"></kaleidr-map>
</div>

<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>

**预期结果:**聊天面板停靠在地图左上角。询问“coffee near Covent Garden”,即可在 Tile 地图上看到地点标记。

聊天元素的属性和样式的作用:

部分作用
map-target="#basemap"指向聊天面板将控制的 Tile 元素的 CSS 选择器。
contained将面板停靠在聊天元素内部;如果省略,面板固定在浏览器窗口左上角。
position:absolute; inset:0将聊天元素覆盖整张地图,使面板位于地图一角。
z-index:1让聊天层显示在地图上方。
pointer-events:none允许用户在面板之外拖动和缩放地图,同时保留面板自身的点击交互。

注意:

  • 默认密钥同时具有 maps 和 ai 权限,所以两个元素可以使用同一个密钥。聊天元素会单独申请会话,每次提问都会消耗组织的 AI 点数。
  • 两个元素的排列顺序没有要求,聊天面板会在需要时查找地图。

面板布局和主题选项请参阅主题与布局,助手的功能与限制请参阅功能和限制。

第 6 步:获知地图加载完成的时间(可选)​

SDK 不提供 ready Promise,元素也不会触发事件。iframe 会在地图绘制完成时向网页发送一条消息;如果绘制失败,还会发送另一条消息:

const target = document.getElementById('basemap');

window.addEventListener('message', (event) => {
if (event.origin !== 'https://map-embed.kaleidr.com') return;
const frame = target.querySelector('iframe');
if (!frame || event.source !== frame.contentWindow) return;

const msg = event.data;
if (!msg || typeof msg.type !== 'string') return;

if (msg.type === 'kaleidr-embed:ready') {
// { type, id: 'kaleidr-morning', source: 'tile' }
console.log('basemap loaded', msg.id);
} else if (msg.type === 'kaleidr-embed:error') {
// { type, id, code: 'maplibre_error', message }, or
// { type, id: null, code: 'no_id', message } when there is no style
console.warn('basemap problem', msg.code, msg.message);
}
});

如果会话请求失败,则不会创建 iframe,因此不会收到消息。错误只会显示在控制台。请参阅无法正常工作时。

完整页面示例​

将文件保存为 index.html,填入密钥,并从该密钥允许的来源通过 HTTP 提供此目录。

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kaleidr basemap</title>
<style>
body { font-family: system-ui, sans-serif; margin: 2rem; }
#basemap { height: 480px; }
</style>
</head>
<body>
<h1>Kaleidr basemap</h1>
<p id="status">Loading the map…</p>

<div id="basemap"></div>
<p>
<button id="paris">Fly to Paris</button>
<button id="night">Night</button>
<button id="day">Morning</button>
</p>

<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<script>
const target = document.getElementById('basemap');
const status = document.getElementById('status');

const handle = Kaleidr.mount(target, {
product: 'tile',
publishableKey: 'kld_pk_live_…',
styleId: 'kaleidr-morning',
center: [-0.1276, 51.5072],
zoom: 11,
});

window.addEventListener('message', (event) => {
if (event.origin !== 'https://map-embed.kaleidr.com') return;
const frame = target.querySelector('iframe');
if (!frame || event.source !== frame.contentWindow) return;
const msg = event.data;
if (msg && msg.type === 'kaleidr-embed:ready') {
status.textContent = 'Map loaded.';
}
});

document.getElementById('paris').addEventListener('click', () => {
handle.setCamera({ center: [2.3522, 48.8566], zoom: 12, duration: 1200 });
});
document.getElementById('night').addEventListener('click', () => {
handle.setStyle('kaleidr-night');
});
document.getElementById('day').addEventListener('click', () => {
handle.setStyle('kaleidr-morning');
});

// In a single-page app, call handle.destroy() when the map leaves the screen.
</script>
</body>
</html>

工作原理​

主题行为
会话SDK 在创建 iframe 之前用密钥换取短期 Tile 会话,并在挂载期间持续续期。交换过程验证密钥并记录一次地图加载。会话不传给 iframe;其 URL 只包含样式与相机参数。
初始视角使用传入的相机;若未传入,使用样式默认视角。
滚动指针位于地图上方时滚动会缩放地图;指针位于地图之外时,滚动会移动网页。触摸屏上拖动可移动地图,双指捏合可缩放地图。
高度挂载时使用容器已有的高度,否则固定为 500 像素。
加载iframe 采用延迟加载,接近可视区域时才开始加载。
移除handle.destroy() 会移除 iframe 并停止会话续期;删除 <kaleidr-map> 元素效果相同。
重新插入将已移除的元素重新插入或移动到另一个父元素,会重新挂载并建立新会话。

地图加载次数的计算方式​

SDK 每获取一次 Tile 会话,就计为一次地图加载:

事件地图加载次数
挂载地图1
地图挂载期间续期会话每次续期计 1
销毁后重新挂载,或重新插入元素1
setCamera、setStyle、平移或缩放0

会话默认有效期为 15 分钟,SDK 在到期前 90 秒续期,无论页面位于前台还是后台。访客停留几分钟通常只消耗一次加载;页面打开一小时约消耗五次。

降低用量的方法:

  • 地图永久隐藏时销毁挂载,例如关闭对话框、切换路由或移除标签页时。
  • 不要在每次渲染时重新创建元素。React、Vue 等框架的用法请参阅框架集成。
  • 切换样式时使用 setStyle,不要重新挂载。

如果组织在当前周期内用完地图加载额度,新会话会被拒绝,并返回 HTTP 429 和 {"detail":"map_load_quota_exceeded"}。已经显示的地图仍会保留,新挂载则不会显示内容。参阅配额和速率限制。

检查是否正常工作​

  • **网页中:**地图可交互,底部显示地图版权和来源说明。
  • **控制台中:**没有包含 [kaleidr 的报错行。
  • **Network 面板中:**从 https://cdn.kaleidr.com 加载 kaleidr.js 和 tile.js;POST …/sdk/sessions 返回 200,JSON 中包含 session_token 与 expires_in;还会向 https://map-embed.kaleidr.com/?style=… 发出文档请求。
  • **事件监听器中:**收到 kaleidr-embed:ready 消息,其 source 为 "tile"。

无法正常工作时​

SDK 在控制台以 [kaleidr:tile] … 形式记录挂载失败。会话被拒绝时只记录 HTTP 状态;具体原因需要在 Network 面板中查看 sessions 请求的响应。403 错误代码位于 detail,map_load_quota_exceeded 也在 detail;429 的 rate_limited 代码位于 error。

现象原因解决方法
页面无显示,控制台出现 …/sdk/sessions 的 CORS 错误及 [kaleidr:tile] 错误密钥无效或已撤销,或者网页来源不在允许范围;拒绝响应不包含 CORS 头。检查密钥,在 kaleidr.com/api-keys 添加完整来源(协议、主机、端口),等待几分钟再刷新。Network 中的请求状态为 401 或 403。
[kaleidr:tile] kaleidr session exchange failed (403)缺少 maps 权限(insufficient_scope)、密钥仅限其他产品(product_not_allowed)或套餐不允许请求(tier_capability_not_allowed)。在 Network 中查看 detail,创建包含默认权限的密钥。
[kaleidr:tile] kaleidr session exchange failed (429)地图额度耗尽(map_load_quota_exceeded)或短时间请求过多(rate_limited)。前者查看 detail,后者查看 error;参阅配额和速率限制。
sessions 返回 404自定义 api-base 时遗漏了 /inference-api。取消覆盖,或使用 https://api.kaleidr.com/inference-api。
[kaleidr:tile] Kaleidr: a server key (kld_sk_…) must never be used in the browser…使用了服务器密钥,SDK 在发送任何请求前就会拒绝。使用可公开使用的密钥。如果服务器密钥曾公开,请立即轮换。
[kaleidr:tile] Kaleidr tile: invalid style "…"…style-id 包含空格或 ? 等非法字符。使用第 2 步列出的样式 ID。
iframe 显示“Couldn't find a map id in the URL.”,监听器收到 code: 'no_id' 和 id: null未传入 style-id,且组织没有默认底图。设置 style-id。
iframe 为空,收到带有 maplibre_error 的 kaleidr-embed:error样式不存在,通常是 ID 拼写错误。使用第 2 步的样式 ID。
[kaleidr] <kaleidr-map> requires product="chat|viewer|editor|tile"product 缺失或拼写错误。设置 product="tile"。
地图始终高 500 像素挂载时元素未设置高度、设置了 display:inline,或 Safari 16.4 之前未使用 display:block。明确设置高度和 display:block。 height
显示空框,控制台提示内容安全策略违规安全策略阻止脚本、会话请求或 iframe。允许开始之前中列出的三个主机。
setStyle 或 setCamera 没有反应方法调用在元素上,或地图仍在加载。对 Kaleidr.mount 返回的句柄调用方法,检查 kaleidr-embed:error 和控制台;提前调用的方法会在就绪后生效。 如果地图在有限等待时间内(通常是 iframe 加载后 10 秒)仍未报告就绪,该调用仍会发出,控制台将显示 [kaleidr] the map frame has not reported ready;出现错误的 iframe 中没有可移动或修改的地图。
修改元素上的 style-id 没有效果预期行为,style-id 只在挂载时读取一次。使用 handle.setStyle,或插入新元素。

限制​

  • 网页不能直接向 Tile 地图添加标记、图层或弹窗,也无法获取点击或相机事件。连接的聊天面板可以在地图上标记地点。
  • 不提供读取当前相机状态的方法。
  • Tile 是用于显示 Kaleidr 底图的受支持产品。
  • 如果密钥不允许网页来源,则无法显示 Tile 地图。

后续步骤​