diff --git a/web/kyushu_compare.html b/web/kyushu_compare.html
index 3784abb..3792a50 100644
--- a/web/kyushu_compare.html
+++ b/web/kyushu_compare.html
@@ -651,6 +651,43 @@ let referenceStyleTemplate=null;
let s52StyleTemplate=null;
let activeLeftStyleTemplate=null;
let activeRightStyleTemplate=null;
+let s52SpriteAtlasPromise=null;
+
+async function loadS52SpriteAtlas(){
+ if(s52SpriteAtlasPromise)return s52SpriteAtlasPromise;
+ s52SpriteAtlasPromise=(async function(){
+ const metaResponse=await fetch('/s52/sprite.json?v=current-release',{cache:'no-store'});
+ if(!metaResponse.ok)throw new Error('S-52 sprite JSON HTTP '+metaResponse.status);
+ const metadata=await metaResponse.json();
+ const image=await new Promise(function(resolve,reject){
+ const img=new Image();
+ img.onload=function(){resolve(img);};
+ img.onerror=function(){reject(new Error('S-52 sprite PNG load failed'));};
+ img.src='/s52/sprite.png?v=current-release';
+ });
+ return {metadata:metadata,image:image};
+ })();
+ return s52SpriteAtlasPromise;
+}
+
+async function ensureS52SpriteImages(map){
+ const atlas=await loadS52SpriteAtlas();
+ const canvas=document.createElement('canvas');
+ const ctx=canvas.getContext('2d',{willReadFrequently:true});
+ let added=0;
+ for(const [name,meta] of Object.entries(atlas.metadata)){
+ if(map.hasImage(name))continue;
+ const width=Number(meta.width)||0, height=Number(meta.height)||0;
+ if(width<=0||height<=0)continue;
+ canvas.width=width; canvas.height=height;
+ ctx.clearRect(0,0,width,height);
+ ctx.drawImage(atlas.image,Number(meta.x)||0,Number(meta.y)||0,width,height,0,0,width,height);
+ const pixels=ctx.getImageData(0,0,width,height);
+ map.addImage(name,pixels,{pixelRatio:Number(meta.pixelRatio)||1});
+ added++;
+ }
+ return added;
+}
function sanitizeReferenceStyle(raw){
const style=JSON.parse(JSON.stringify(raw));
@@ -742,15 +779,22 @@ async function loadComparisonStyles(){
}
}
-leftMap.on("style.load",function(){
+leftMap.on("style.load",async function(){
const sources=Object.keys((leftMap.getStyle() || {}).sources || {});
if(sources.includes("cm95")){
+ try{
+ await ensureS52SpriteImages(leftMap);
+ }catch(err){
+ console.error(err);
+ setState(leftState,"S-52 sprite 注册失败:"+(err.message||err),"err");
+ }
installRuntimePreviewLayers(leftMap);
setState(leftState,"当前 Production / S-52 style" + (debugRuntimePreview.checked ? " + runtime preview" : ""),"ok");
}else if(sources.includes("navsea_delivery")){
setState(leftState,"当前 Production / extentfix style","ok");
}
applyDebugStyles();
+ refreshRuntimeRuleExecutor();
refreshLightArcFeatures();
});
rightMap.on("style.load",applyDebugStyles);