图像资源
共同地图入口提供 addImage、updateImage、removeImage、getImage、hasImage 和 listImages。已加载样式 sprite 与运行时图像使用同一组查询、更新和删除语义。脚本从 sqsmap 导入 map;独立网页 SDK 使用 MapView。查询使用 await,链式写入用 await map.sqs.flush() 确认;独立 SDK 对应 await view.flush()。确认应用不代表所有网络资源已就绪。
// @gis-api 0.5-session
// @permissions ["project.read","map.write"]
import {map} from "sqsmap";
map.addImage("marker", {width:1,height:1,data:new Uint8Array([0,0,255,255])}, {pixelRatio:1,sdf:false});
await map.sqs.flush();
const image = await map.getImage("marker");
image.data.data.set([255,0,0,255]);
map.updateImage("marker", image.data);
await map.sqs.flush();
export default {ids:await map.listImages(),info:await map.sqs.getImageInfo("marker")};
输入为未预乘透明度 RGBA8,data 可用 Uint8Array、Uint8ClampedArray 或普通字节数组。写入时捕获像素,之后修改原数组不改变地图。getImage 返回 {data:{width,height,data:Uint8Array},pixelRatio,sdf};缺失时为 undefined。返回像素是用户拥有的独立副本,可以编辑后交给 updateImage;元数据对象为只读。更新必须保持宽高,并保留原 pixelRatio/sdf。脚本扩展 map.sqs.getImageInfo(id)(独立 SDK 为 view.getImageInfo)给出 source、imageInstanceId、精确字符串 revision 和内存信息。删除后重建得到新的身份;旧副本仍有效。
128 个用户注册/覆盖图像,边长1..512,每图1MiB、每地图16MiB原始像素;合成图集另受2048边长限制。pixelRatio 为0.125..16,sdf 为布尔值,默认1/false。样式中的大图可读取;更新也遵守同一原始图像预算。脚本图像写入 JSON 上限8MiB,全部排队参数总量16MiB;普通调用仍为64KiB。脚本运行环境还保留总内存与最终结果预算,不应将整份大型像素导出为执行摘要。
样式 sprite 更新保留原身份并增加修订;相同尺寸覆盖可复用原图集位置。删除使用同代标记,迟到的 sprite 响应不能复活已删图像。新样式代/清空释放旧资源;失败样式回滚恢复旧图像。重复标识、尺寸/字节错误、未知参数、图集或事件预算不足均明确报错,失败保留原像素和图集。
持续脚本通过 map.on("sqs.imageschange", listener) 监听成功的显式图像写入;payload 为历史 method/id/imageCount/runtimeByteLength。取消订阅、停止脚本与销毁清理监听。独立 SDK 可用 view.onImagesChange。此事件不代表下载进度或样式已加载;示例依据真实 basemapStatus 与 view 通知初始化,署名用公开查询和变更事件呈现。图层和控件 UI 由使用方实现。
动态库 ABI1 新增能力位 SQSM_MAP_IMAGES=1048576 和 sqsm_map_image_json。请求 {method,args},8MiB 请求/32MiB 输出预算;getImage 缺失在线路上为 null,JS 转换为 undefined。查询不改变命令水位;写入使用共同确认和事件。输出独立拥有,失败清零,可在地图销毁后读取,再用 sqsm_map_bytes_free 释放。请使用配套 SDK/声明和能力查询,不把旧库中的缺失方法视为成功。
相同的跨宿主脚本 / 完整 HTML。下面的网页代码包括三个操作按钮、查询、初始化、事件、署名和销毁清理,可放到通过 HTTP(S) 提供的 HTML 中。示例使用本站附带的合成离线矢量瓦片,不依赖外部地图密钥;引用的开发 SDK 需与本站资源一起部署。
loadImage、可伸缩图片、动态图像回调和完整字体回退仍在后续实施,未支持选项会报 CAPABILITY_UNAVAILABLE。三端方法与语义尽量统一;移动应用脚本宿主、Windows/macOS、硬件与正式发行仍分别验收。SqsMap 引擎自研,仅参考 MapLibre 公共 Map 方法 的名称与参数语义。
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>SqsMap image resources</title>
<style>body{margin:0;font:16px system-ui;background:#f5f7fa;color:#182330}main{display:grid;grid-template-columns:1fr 280px;min-height:100vh}#map{min-height:70vh}aside{padding:20px}button{padding:8px;margin:4px}pre{white-space:pre-wrap;overflow-wrap:anywhere}@media(max-width:650px){main{grid-template-columns:1fr}}</style>
<main><div id="map"></div><aside><h1>Editable map image</h1><button id="add" disabled>Add blue image</button><button id="update" disabled>Update to red</button><button id="remove" disabled>Remove image</button><button id="query" disabled>Read image metadata</button><button id="destroy">Destroy map</button><p id="attribution"></p><pre id="status">Starting</pre></aside></main>
<script type="module">
import {MapView} from 'https://www.sqsmap.com/sdk/sqsmap-core/dist/index.js';
const status=document.querySelector('#status'),buttons=['add','update','remove','query'].map(id=>document.getElementById(id));let view,closed=false,busy=false,initialized=false,offImages,offView,offAttributions,offError;
function image(color){const data=new Uint8Array(16*16*4);for(let i=0;i<data.length;i+=4)data.set(color,i);return {width:16,height:16,data};}
async function refresh(){if(!view||closed)return;const exists=await view.hasImage('marker');if(closed)return;buttons[0].disabled=busy||exists||!initialized;buttons[1].disabled=buttons[2].disabled=busy||!exists;buttons[3].disabled=busy;}
async function perform(fn){if(closed||busy)return;busy=true;try{await refresh();await fn();await view.flush({render:true});await refresh();}catch(error){if(!closed)status.textContent=String(error);}finally{busy=false;if(!closed)await refresh();}}
buttons[0].addEventListener('click',()=>perform(()=>view.addImage('marker',image([0,0,255,255]))));
buttons[1].addEventListener('click',()=>perform(()=>view.updateImage('marker',image([255,0,0,255]))));
buttons[2].addEventListener('click',()=>perform(()=>view.removeImage('marker')));
buttons[3].addEventListener('click',()=>perform(async()=>{const snapshot=await view.getImage('marker');status.textContent=JSON.stringify({ids:await view.listImages(),info:await view.getImageInfo('marker'),firstPixel:snapshot?Array.from(snapshot.data.data.slice(0,4)):null},null,2);}));
function destroy(){if(closed)return;closed=true;offImages?.();offView?.();offAttributions?.();offError?.();view?.destroy();for(const button of buttons)button.disabled=true;status.textContent='Map destroyed; observers removed.';}
document.querySelector('#destroy').addEventListener('click',destroy);window.addEventListener('pagehide',destroy,{once:true});
try{
view=await MapView.create(document.querySelector('#map'),{worker:false});if(closed){view.destroy();throw Error('Initialization cancelled.');}
if(view.capabilities.imageRegistry!==true)throw Error('A matching image-capable SDK is required.');
offImages=view.onImagesChange(event=>{if(!closed){status.textContent=JSON.stringify(event,null,2);refresh().catch(error=>{if(!closed)status.textContent=String(error);});}});
offError=view.on('error',event=>{if(!closed)status.textContent=event.message;});
async function attribution(){try{const value=await view.getAttributions();if(!closed)document.querySelector('#attribution').textContent=value.text;}catch(error){if(!closed)status.textContent=String(error);}}
offAttributions=view.onAttributionsChange(attribution);await attribution();
// Read actual style progress, then initialize the image once. No fixed loading delay.
offView=view.on('view',()=>{if(initialized||closed||!['ready','degraded'].includes(view.basemapStatus.state)||view.basemapStatus.readyTiles===0)return;initialized=true;perform(()=>view.addImage('marker',image([0,0,255,255])));});
view.jumpTo({center:[0,0],zoom:0});view.setStyle('https://www.sqsmap.com/sdk/sqsmap-core/image-fixtures/style.json');await view.flush();await refresh();
}catch(error){if(!closed)status.textContent=String(error);}
</script></html>
外部图片加载见 下载外部图片.
共同点图片symbol也已接通缺图补全与SDF染色,见符号图片资源与事件。普通文字/碰撞/三维符号和移动宿主继续后续。