Anonymous
Растровые слои «заморозить» на увеличении, они были впервые добавлены и обновляются только после того, как я увеличил ма
Сообщение
Anonymous » 15 сен 2025, 16:30
Проблема < /strong>: Я использую листовку с Georaster + Georaster-Layer-For-Leaflet, чтобы переключать несколько однополосных геотиф-растра (только один видимый за раз). Когда я переключаю, какой растровый виден, ранее добавленные растровые визуально «палки» на уровне масштабирования, где он был впервые отображен. Новый растровый не появляется, пока я не выполню какое -либо действие по увеличению; После увеличения увеличения появляется правильный растровый. Другими словами, холст кажется замороженным до тех пор, пока не будет запущено событие увеличения*. Файлы публично читаются через firebasestorage.googleapis.com. CORS включен на ведро и позволяет Get/Head с заголовком ответа типа контента.
Пример того, что произошло
код :
Код: Выделить всё
(function (app) {
'use strict';
// -------------------------------------------------
// Helpers
// -------------------------------------------------
function computeLegendRange(legend) {
if (!legend || !Array.isArray(legend.classes) || legend.classes.length === 0) {
return { min: 0, max: 1 };
}
const bounds = legend.classes
.map(c => (typeof c.upper_bound === 'number' ? c.upper_bound : null))
.filter(v => v !== null && isFinite(v));
if (bounds.length === 0) {
return { min: 0, max: 1 };
}
return { min: Math.min(...bounds), max: Math.max(...bounds) };
}
function createGeoRasterLayer(layerState) {
const georaster = layerState.georaster;
const config = layerState.config;
const colorClasses = (config.legend && config.legend.classes) ? config.legend.classes : [];
return new GeoRasterLayer({
georaster: georaster,
pane: layerState.paneId,
opacity: 0.7,
bounds: layerState.bounds,
resolution: 256,
updateWhenZooming: true,
updateWhenIdle: true,
updateInterval: 0,
keepBuffer: 0,
pixelValuesToColorFn: values => {
const value = values[0];
if (value === null || value === undefined || isNaN(value) || value === 0 || value === georaster.noDataValue) {
return null;
}
const [minFilter, maxFilter] = layerState.filterRange;
if (value < minFilter || value > maxFilter) {
return null;
}
for (let i = 0; i < colorClasses.length; i++) {
const cls = colorClasses[i];
if (typeof cls.upper_bound === 'number' && value 0) {
const from = ((minVal - min) / range) * 100;
const to = ((maxVal - min) / range) * 100;
selection.style.left = `${from}%`;
selection.style.right = `${100 - to}%`;
}
}
function updateStateFromSliders() {
let minVal = parseFloat(minSlider.value);
let maxVal = parseFloat(maxSlider.value);
if (minVal > maxVal) {
[minVal, maxVal] = [maxVal, minVal];
minSlider.value = minVal;
maxSlider.value = maxVal;
}
layerState.filterRange = [minVal, maxVal];
updateSliderVisuals();
}
minSlider.addEventListener('input', updateStateFromSliders);
maxSlider.addEventListener('input', updateStateFromSliders);
minSlider.addEventListener('change', () => applyRasterFilter(layerId));
maxSlider.addEventListener('change', () => applyRasterFilter(layerId));
updateSliderVisuals();
return container;
}
function createOpacitySlider(layerId) {
const layerState = app.activeRasterLayers[layerId];
const controlContainer = document.createElement('div');
controlContainer.className = 'opacity-control-container';
const initialOpacity = layerState.layer ? layerState.layer.options.opacity : 0.7;
controlContainer.innerHTML = `
[/i]
[i]
${Math.round(initialOpacity * 100)}%`;
controlContainer.querySelector('input').addEventListener('input', (e) => {
const opacity = parseFloat(e.target.value);
if (layerState.layer) layerState.layer.setOpacity(opacity);
controlContainer.querySelector('span').textContent = `${Math.round(opacity * 100)}%`;
});
return controlContainer;
}
function toggleExtraControl(type, button, layerId, container) {
const wasActive = button.classList.contains('active');
document.querySelectorAll(`#wrapper_controls_${layerId} .opacity-tool-btn, #wrapper_controls_${layerId} .filter-tool-btn`).forEach(btn => btn.classList.remove('active'));
container.innerHTML = '';
container.style.display = 'none';
if (!wasActive) {
button.classList.add('active');
const newControl = (type === 'opacity') ? createOpacitySlider(layerId) : createRangeFilterControl(layerId);
container.appendChild(newControl);
container.style.display = 'block';
}
}
// -------------------------------------------------
// Point analysis (value at the clicked point)
// -------------------------------------------------
function toggleInfoTool(button, layerId) {
const layerState = app.activeRasterLayers[layerId];
if (!layerState || !layerState.isLoaded) {
alert('Por favor, carregue a camada primeiro.');
return;
}
layerState.infoToolActive = !layerState.infoToolActive;
button.classList.toggle('active', layerState.infoToolActive);
const anyToolActive = Object.values(app.activeRasterLayers).some(state => state.infoToolActive);
if (anyToolActive) {
app.map.on('click', updatePixelValueOnClick);
} else {
app.map.off('click', updatePixelValueOnClick);
const pixelValuePanel = document.getElementById('pixelValuePanel');
if (pixelValuePanel) pixelValuePanel.style.display = 'none';
if (app.clickPin) app.map.removeLayer(app.clickPin);
}
}
function updatePixelValueOnClick(e) {
const { lat, lng } = e.latlng;
const panel = document.getElementById('pixelValuePanel');
const content = document.getElementById('pixelValueContent');
let htmlContent = `Latitude:[/b] ${lat.toFixed(4)}[b]Longitude:[/b] ${lng.toFixed(4)}`;[b] for (const layerId in app.activeRasterLayers) {
const layerState = app.activeRasterLayers[layerId];
if (layerState.visible && layerState.infoToolActive && layerState.georaster) {
const georaster = layerState.georaster;
let valueText = 'Fora da área de dados';
if (lng >= georaster.xmin && lng = georaster.ymin && lat toggleInfoTool(infoBtn, layerId));
opacityBtn.addEventListener('click', () => toggleExtraControl('opacity', opacityBtn, layerId, controlsContainer));
filterBtn.addEventListener('click', () => toggleExtraControl('filter', filterBtn, layerId, controlsContainer));
}
// -------------------------------------------------
// Layer Visibility
// -------------------------------------------------
function hideRasterLayer(id) {
const st = app.activeRasterLayers[id];
if (!st) return;
forceCleanupRasterLayer(id);
st.visible = false;
if (st.infoToolActive) {
const infoBtn = document.querySelector(`.info-tool-btn[data-layer-id="${id}"]`);
if (infoBtn) infoBtn.classList.remove('active');
st.infoToolActive = false;
const anyToolActive = Object.values(app.activeRasterLayers).some(state => state.infoToolActive);
if (!anyToolActive) {
app.map.off('click', updatePixelValueOnClick);
const panel = document.getElementById('pixelValuePanel');
if (panel) panel.style.display = 'none';
if (app.clickPin) app.map.removeLayer(app.clickPin);
}
}
}
function showRasterLayer(id) {
const st = app.activeRasterLayers[id];
if (!st || !st.georaster) return;
st.paneId = `raster-${id}`;
if (!app.map.getPane(st.paneId)) {
app.map.createPane(st.paneId);
// app.__rZ = (app.__rZ || 1050) + 1;
app.map.getPane(st.paneId).style.zIndex = app.__rZ;
}
if (st.layer) {
forceCleanupRasterLayer(id);
}
st.layer = createGeoRasterLayer(st);
st.visible = true;
st.layer.addTo(app.map);
if (typeof st.layer.redraw === 'function') {
st.layer.redraw();
}
app.map.once('idle', () => { if (st.visible && st.layer?.redraw) st.layer.redraw(); });
app.map.once('zoomend', () => { if (st.visible && st.layer?.redraw) st.layer.redraw(); });
}
// -------------------------------------------------
// Raster loading
// -------------------------------------------------
async function loadRasterLayer(layerId) {
const layerState = app.activeRasterLayers[layerId];
const config = layerState.config;
const icon = document.getElementById(`icon_${layerId}`);
icon.className = 'fas fa-spinner fa-spin layer-action-icon';
try {
const response = await fetch(config.path, { mode: 'cors' });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const arrayBuffer = await response.arrayBuffer();
const georaster = await parseGeoraster(arrayBuffer);
layerState.georaster = georaster;
layerState.bounds = L.latLngBounds([
[georaster.ymin, georaster.xmin],
[georaster.ymax, georaster.xmax]
]);
layerState.legendRange = computeLegendRange(config.legend);
layerState.filterRange = [layerState.legendRange.min, layerState.legendRange.max];
layerState.isLoaded = true;
const checkbox = document.getElementById(`cb_${layerId}`);
checkbox.disabled = false;
checkbox.checked = true;
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
const controlsWrapper = document.getElementById(`wrapper_controls_${layerId}`);
const controlsContainer = document.getElementById(`controls_${layerId}`);
createOperationalControls(layerId, controlsWrapper, controlsContainer);
icon.className = 'fas fa-check layer-action-icon';
setTimeout(() => { icon.className = 'fas fa-download layer-action-icon'; }, 1200);
} catch (error) {
console.error(`Falha ao carregar camada raster ${layerId}:`, error);
icon.className = 'fas fa-download layer-action-icon';
alert(`Não foi possível carregar a camada ${config.name}.`);
}
}
// -------------------------------------------------
// Initialization
// -------------------------------------------------
function init() {
// Point Analysis Panel Configuration
const panelHeader = document.querySelector('#pixelValuePanel .popup-header h4');
if (panelHeader) panelHeader.innerHTML = `[/i] Análise de Ponto`;
const panelContent = document.getElementById('pixelValueContent');
if (panelContent) {
const removePinBtn = document.createElement('button');
removePinBtn.id = 'removeAnalysisPinBtn';
removePinBtn.className = 'panel-action-button danger';
removePinBtn.innerHTML = '[i][/i] Remover Marcador';
removePinBtn.style.cssText = 'display: none; width: 100%; margin-top: 10px;';
panelContent.after(removePinBtn);
removePinBtn.addEventListener('click', () => {
if (app.clickPin) {
app.map.removeLayer(app.clickPin);
app.clickPin = null;
removePinBtn.style.display = 'none';
}
});
}
const closeBtn = document.getElementById('closePixelValuePanel');
if (closeBtn) {
closeBtn.addEventListener('click', () => {
Object.keys(app.activeRasterLayers).forEach(layerId => {
const layerState = app.activeRasterLayers[layerId];
if (layerState.infoToolActive) {
layerState.infoToolActive = false;
const infoBtn = document.querySelector(`.info-tool-btn[data-layer-id="${layerId}"]`);
if (infoBtn) infoBtn.classList.remove('active');
}
});
app.map.off('click', updatePixelValueOnClick);
const pixelValuePanel = document.getElementById('pixelValuePanel');
if (pixelValuePanel) pixelValuePanel.style.display = 'none';
if (app.clickPin) app.map.removeLayer(app.clickPin);
});
}
// Building the Layer UI
const rasterList = app.config.rasterLayers;
if (!Array.isArray(rasterList) || rasterList.length === 0) return;
app.activeRasterLayers = app.activeRasterLayers || {};
rasterList.forEach(rasterConfig => {
const groupContainer = document.getElementById(`group-content-${rasterConfig.group}`);
if (!groupContainer) return;
const layerId = rasterConfig.id;
app.activeRasterLayers[layerId] = {
layer: null, config: rasterConfig, georaster: null,
visible: false, isLoaded: false, filterRange: null,
bounds: null, legendRange: computeLegendRange(rasterConfig.legend),
infoToolActive: false, paneId: null,
legend: { type: 'raster', title: rasterConfig.name, ...(rasterConfig.legend || {}) }
};
const listItem = document.createElement('div');
listItem.className = 'layer-group-item';
listItem.innerHTML = `
[i][/i]
[i]
${rasterConfig.name}
[/i]
`;
groupContainer.appendChild(listItem);
document.getElementById(`icon_${layerId}`).addEventListener('click', () => loadRasterLayer(layerId));
const checkbox = document.getElementById(`cb_${layerId}`);
checkbox.addEventListener('change', (e) => {
const isChecked = e.target.checked;
if (!app.activeRasterLayers[layerId].isLoaded) { e.target.checked = false; return; }
if (isChecked) {
Object.keys(app.activeRasterLayers).forEach(otherId => {
if (otherId !== layerId && app.activeRasterLayers[otherId]?.visible) {
const cb = document.getElementById(`cb_${otherId}`);
if (cb) cb.checked = false;
hideRasterLayer(otherId);
}
});
showRasterLayer(layerId);
} else {
hideRasterLayer(layerId);
}
if (app.legend && app.legend.update) {
app.legend.update();
}
});
});
}
// -------------------------------------------------
// Public API
// -------------------------------------------------
app.raster = {
init,
loadRasterLayer,
showRasterLayer,
hideRasterLayer,
toggleInfoTool,
updatePixelValueOnClick
};
app.initRasterLayers = init;
})(window.app = window.app || {});
Вопросы :
*- есть ли известная проблема с GeorasterLayer (или его внутренние внутренние знания L.Gridlayer), где холст не лишается аннулирования до полного разбитого. рендеринг без необходимости увеличения? Toggle? После переключения, на экране все еще показывается растровый A на уровне масштабирования, где он был впервые добавлен. Только после Zoom (In или OUT) делает Raster B render. < /P>
то, что я попробовал < /strong>: < /p>
*- вызовов Layer.redraw () сразу после Addto (map), а также на map.once ('idle') /map.once ('Zoomend'). 0, UpdateWhenzooming: True, UpdateWhenidle: True, UpdateInterval: 0.
[*] Удаление слоя и очистку Dom Pane (pane.innerhtml = '') перед воссозданием. /> Проверка Cors и Fetch; Нагрузка данных хорошо, а пиксели читаются правильно. Я не полагаюсь на Zoomstart/Zoomend, чтобы вызвать первое рендеринг.*
Подробнее здесь:
https://stackoverflow.com/questions/797 ... resh-after
1757943009
Anonymous
[b] Проблема < /strong>: [b] Я использую листовку с Georaster + Georaster-Layer-For-Leaflet, чтобы переключать несколько однополосных геотиф-растра (только один видимый за раз). Когда я переключаю, какой растровый виден, ранее добавленные растровые визуально «палки» на уровне масштабирования, где он был впервые отображен. Новый растровый не появляется, пока я не выполню какое -либо действие по увеличению; После увеличения увеличения появляется правильный растровый. Другими словами, холст кажется замороженным до тех пор, пока не будет запущено событие увеличения*. Файлы публично читаются через firebasestorage.googleapis.com. CORS включен на ведро и позволяет Get/Head с заголовком ответа типа контента. Пример того, что произошло код [/b]: [code](function (app) { 'use strict'; // ------------------------------------------------- // Helpers // ------------------------------------------------- function computeLegendRange(legend) { if (!legend || !Array.isArray(legend.classes) || legend.classes.length === 0) { return { min: 0, max: 1 }; } const bounds = legend.classes .map(c => (typeof c.upper_bound === 'number' ? c.upper_bound : null)) .filter(v => v !== null && isFinite(v)); if (bounds.length === 0) { return { min: 0, max: 1 }; } return { min: Math.min(...bounds), max: Math.max(...bounds) }; } function createGeoRasterLayer(layerState) { const georaster = layerState.georaster; const config = layerState.config; const colorClasses = (config.legend && config.legend.classes) ? config.legend.classes : []; return new GeoRasterLayer({ georaster: georaster, pane: layerState.paneId, opacity: 0.7, bounds: layerState.bounds, resolution: 256, updateWhenZooming: true, updateWhenIdle: true, updateInterval: 0, keepBuffer: 0, pixelValuesToColorFn: values => { const value = values[0]; if (value === null || value === undefined || isNaN(value) || value === 0 || value === georaster.noDataValue) { return null; } const [minFilter, maxFilter] = layerState.filterRange; if (value < minFilter || value > maxFilter) { return null; } for (let i = 0; i < colorClasses.length; i++) { const cls = colorClasses[i]; if (typeof cls.upper_bound === 'number' && value 0) { const from = ((minVal - min) / range) * 100; const to = ((maxVal - min) / range) * 100; selection.style.left = `${from}%`; selection.style.right = `${100 - to}%`; } } function updateStateFromSliders() { let minVal = parseFloat(minSlider.value); let maxVal = parseFloat(maxSlider.value); if (minVal > maxVal) { [minVal, maxVal] = [maxVal, minVal]; minSlider.value = minVal; maxSlider.value = maxVal; } layerState.filterRange = [minVal, maxVal]; updateSliderVisuals(); } minSlider.addEventListener('input', updateStateFromSliders); maxSlider.addEventListener('input', updateStateFromSliders); minSlider.addEventListener('change', () => applyRasterFilter(layerId)); maxSlider.addEventListener('change', () => applyRasterFilter(layerId)); updateSliderVisuals(); return container; } function createOpacitySlider(layerId) { const layerState = app.activeRasterLayers[layerId]; const controlContainer = document.createElement('div'); controlContainer.className = 'opacity-control-container'; const initialOpacity = layerState.layer ? layerState.layer.options.opacity : 0.7; controlContainer.innerHTML = ` [/i] [i] ${Math.round(initialOpacity * 100)}%`; controlContainer.querySelector('input').addEventListener('input', (e) => { const opacity = parseFloat(e.target.value); if (layerState.layer) layerState.layer.setOpacity(opacity); controlContainer.querySelector('span').textContent = `${Math.round(opacity * 100)}%`; }); return controlContainer; } function toggleExtraControl(type, button, layerId, container) { const wasActive = button.classList.contains('active'); document.querySelectorAll(`#wrapper_controls_${layerId} .opacity-tool-btn, #wrapper_controls_${layerId} .filter-tool-btn`).forEach(btn => btn.classList.remove('active')); container.innerHTML = ''; container.style.display = 'none'; if (!wasActive) { button.classList.add('active'); const newControl = (type === 'opacity') ? createOpacitySlider(layerId) : createRangeFilterControl(layerId); container.appendChild(newControl); container.style.display = 'block'; } } // ------------------------------------------------- // Point analysis (value at the clicked point) // ------------------------------------------------- function toggleInfoTool(button, layerId) { const layerState = app.activeRasterLayers[layerId]; if (!layerState || !layerState.isLoaded) { alert('Por favor, carregue a camada primeiro.'); return; } layerState.infoToolActive = !layerState.infoToolActive; button.classList.toggle('active', layerState.infoToolActive); const anyToolActive = Object.values(app.activeRasterLayers).some(state => state.infoToolActive); if (anyToolActive) { app.map.on('click', updatePixelValueOnClick); } else { app.map.off('click', updatePixelValueOnClick); const pixelValuePanel = document.getElementById('pixelValuePanel'); if (pixelValuePanel) pixelValuePanel.style.display = 'none'; if (app.clickPin) app.map.removeLayer(app.clickPin); } } function updatePixelValueOnClick(e) { const { lat, lng } = e.latlng; const panel = document.getElementById('pixelValuePanel'); const content = document.getElementById('pixelValueContent'); let htmlContent = `Latitude:[/b] ${lat.toFixed(4)}[b]Longitude:[/b] ${lng.toFixed(4)}`;[b] for (const layerId in app.activeRasterLayers) { const layerState = app.activeRasterLayers[layerId]; if (layerState.visible && layerState.infoToolActive && layerState.georaster) { const georaster = layerState.georaster; let valueText = 'Fora da área de dados'; if (lng >= georaster.xmin && lng = georaster.ymin && lat toggleInfoTool(infoBtn, layerId)); opacityBtn.addEventListener('click', () => toggleExtraControl('opacity', opacityBtn, layerId, controlsContainer)); filterBtn.addEventListener('click', () => toggleExtraControl('filter', filterBtn, layerId, controlsContainer)); } // ------------------------------------------------- // Layer Visibility // ------------------------------------------------- function hideRasterLayer(id) { const st = app.activeRasterLayers[id]; if (!st) return; forceCleanupRasterLayer(id); st.visible = false; if (st.infoToolActive) { const infoBtn = document.querySelector(`.info-tool-btn[data-layer-id="${id}"]`); if (infoBtn) infoBtn.classList.remove('active'); st.infoToolActive = false; const anyToolActive = Object.values(app.activeRasterLayers).some(state => state.infoToolActive); if (!anyToolActive) { app.map.off('click', updatePixelValueOnClick); const panel = document.getElementById('pixelValuePanel'); if (panel) panel.style.display = 'none'; if (app.clickPin) app.map.removeLayer(app.clickPin); } } } function showRasterLayer(id) { const st = app.activeRasterLayers[id]; if (!st || !st.georaster) return; st.paneId = `raster-${id}`; if (!app.map.getPane(st.paneId)) { app.map.createPane(st.paneId); // app.__rZ = (app.__rZ || 1050) + 1; app.map.getPane(st.paneId).style.zIndex = app.__rZ; } if (st.layer) { forceCleanupRasterLayer(id); } st.layer = createGeoRasterLayer(st); st.visible = true; st.layer.addTo(app.map); if (typeof st.layer.redraw === 'function') { st.layer.redraw(); } app.map.once('idle', () => { if (st.visible && st.layer?.redraw) st.layer.redraw(); }); app.map.once('zoomend', () => { if (st.visible && st.layer?.redraw) st.layer.redraw(); }); } // ------------------------------------------------- // Raster loading // ------------------------------------------------- async function loadRasterLayer(layerId) { const layerState = app.activeRasterLayers[layerId]; const config = layerState.config; const icon = document.getElementById(`icon_${layerId}`); icon.className = 'fas fa-spinner fa-spin layer-action-icon'; try { const response = await fetch(config.path, { mode: 'cors' }); if (!response.ok) throw new Error(`HTTP ${response.status}`); const arrayBuffer = await response.arrayBuffer(); const georaster = await parseGeoraster(arrayBuffer); layerState.georaster = georaster; layerState.bounds = L.latLngBounds([ [georaster.ymin, georaster.xmin], [georaster.ymax, georaster.xmax] ]); layerState.legendRange = computeLegendRange(config.legend); layerState.filterRange = [layerState.legendRange.min, layerState.legendRange.max]; layerState.isLoaded = true; const checkbox = document.getElementById(`cb_${layerId}`); checkbox.disabled = false; checkbox.checked = true; checkbox.dispatchEvent(new Event('change', { bubbles: true })); const controlsWrapper = document.getElementById(`wrapper_controls_${layerId}`); const controlsContainer = document.getElementById(`controls_${layerId}`); createOperationalControls(layerId, controlsWrapper, controlsContainer); icon.className = 'fas fa-check layer-action-icon'; setTimeout(() => { icon.className = 'fas fa-download layer-action-icon'; }, 1200); } catch (error) { console.error(`Falha ao carregar camada raster ${layerId}:`, error); icon.className = 'fas fa-download layer-action-icon'; alert(`Não foi possível carregar a camada ${config.name}.`); } } // ------------------------------------------------- // Initialization // ------------------------------------------------- function init() { // Point Analysis Panel Configuration const panelHeader = document.querySelector('#pixelValuePanel .popup-header h4'); if (panelHeader) panelHeader.innerHTML = `[/i] Análise de Ponto`; const panelContent = document.getElementById('pixelValueContent'); if (panelContent) { const removePinBtn = document.createElement('button'); removePinBtn.id = 'removeAnalysisPinBtn'; removePinBtn.className = 'panel-action-button danger'; removePinBtn.innerHTML = '[i][/i] Remover Marcador'; removePinBtn.style.cssText = 'display: none; width: 100%; margin-top: 10px;'; panelContent.after(removePinBtn); removePinBtn.addEventListener('click', () => { if (app.clickPin) { app.map.removeLayer(app.clickPin); app.clickPin = null; removePinBtn.style.display = 'none'; } }); } const closeBtn = document.getElementById('closePixelValuePanel'); if (closeBtn) { closeBtn.addEventListener('click', () => { Object.keys(app.activeRasterLayers).forEach(layerId => { const layerState = app.activeRasterLayers[layerId]; if (layerState.infoToolActive) { layerState.infoToolActive = false; const infoBtn = document.querySelector(`.info-tool-btn[data-layer-id="${layerId}"]`); if (infoBtn) infoBtn.classList.remove('active'); } }); app.map.off('click', updatePixelValueOnClick); const pixelValuePanel = document.getElementById('pixelValuePanel'); if (pixelValuePanel) pixelValuePanel.style.display = 'none'; if (app.clickPin) app.map.removeLayer(app.clickPin); }); } // Building the Layer UI const rasterList = app.config.rasterLayers; if (!Array.isArray(rasterList) || rasterList.length === 0) return; app.activeRasterLayers = app.activeRasterLayers || {}; rasterList.forEach(rasterConfig => { const groupContainer = document.getElementById(`group-content-${rasterConfig.group}`); if (!groupContainer) return; const layerId = rasterConfig.id; app.activeRasterLayers[layerId] = { layer: null, config: rasterConfig, georaster: null, visible: false, isLoaded: false, filterRange: null, bounds: null, legendRange: computeLegendRange(rasterConfig.legend), infoToolActive: false, paneId: null, legend: { type: 'raster', title: rasterConfig.name, ...(rasterConfig.legend || {}) } }; const listItem = document.createElement('div'); listItem.className = 'layer-group-item'; listItem.innerHTML = ` [i][/i] [i] ${rasterConfig.name} [/i] `; groupContainer.appendChild(listItem); document.getElementById(`icon_${layerId}`).addEventListener('click', () => loadRasterLayer(layerId)); const checkbox = document.getElementById(`cb_${layerId}`); checkbox.addEventListener('change', (e) => { const isChecked = e.target.checked; if (!app.activeRasterLayers[layerId].isLoaded) { e.target.checked = false; return; } if (isChecked) { Object.keys(app.activeRasterLayers).forEach(otherId => { if (otherId !== layerId && app.activeRasterLayers[otherId]?.visible) { const cb = document.getElementById(`cb_${otherId}`); if (cb) cb.checked = false; hideRasterLayer(otherId); } }); showRasterLayer(layerId); } else { hideRasterLayer(layerId); } if (app.legend && app.legend.update) { app.legend.update(); } }); }); } // ------------------------------------------------- // Public API // ------------------------------------------------- app.raster = { init, loadRasterLayer, showRasterLayer, hideRasterLayer, toggleInfoTool, updatePixelValueOnClick }; app.initRasterLayers = init; })(window.app = window.app || {}); [/code] [b] Вопросы [/b]: *- есть ли известная проблема с GeorasterLayer (или его внутренние внутренние знания L.Gridlayer), где холст не лишается аннулирования до полного разбитого. рендеринг без необходимости увеличения? Toggle? После переключения, на экране все еще показывается растровый A на уровне масштабирования, где он был впервые добавлен. Только после Zoom (In или OUT) делает Raster B render. < /P> то, что я попробовал < /strong>: < /p> *- вызовов Layer.redraw () сразу после Addto (map), а также на map.once ('idle') /map.once ('Zoomend'). 0, UpdateWhenzooming: True, UpdateWhenidle: True, UpdateInterval: 0. [*] Удаление слоя и очистку Dom Pane (pane.innerhtml = '') перед воссозданием. /> Проверка Cors и Fetch; Нагрузка данных хорошо, а пиксели читаются правильно. Я не полагаюсь на Zoomstart/Zoomend, чтобы вызвать первое рендеринг.* Подробнее здесь: [url]https://stackoverflow.com/questions/79765197/raster-layers-freeze-at-the-zoom-they-were-first-added-and-only-refresh-after[/url]