Anonymous
Синие линии границы сетки/плитки появляются во время масштабирования после рисования фигур в @vis.gl/react-google-maps
Сообщение
Anonymous » 15 дек 2025, 14:36
Я использую
@vis.gl/react-google-maps с
библиотекой рисования Карт Google для рисования многоугольников, прямоугольников и кругов.
Карта работает правильно, но
синие линии сетки (границы плиток/швы проекций) появляются
только при увеличении или уменьшении масштаба после рисования фигуры .
Линии мигают во время масштабирования и выглядят следующим образом: Границы плиток отладки Google Maps.
Важные наблюдения:
Линии сетки не появляются при начальной загрузке
Они начинают появляться только после рисования многоугольников/прямоугольников/кругов
Удаление фигур нет всегда удаляйте сетку
Проблема возникает только при увеличении/уменьшении масштаба
Я понимаю, что это, по-видимому,
внутренние плиточные/проекционные швы Google Maps , которые становятся видимыми, когда карта переключается с растрового на векторный/WebGL рендеринг.
Я попробовал следующее,
ничего не решило проблему :
Удаление MapId
Отключение пользовательского интерфейса и элементов управления по умолчанию
Изменение обработки жестов
Принудительный растровый режим
Удаление DrawingManager
Изменения CSS/zIndex
Код: Выделить всё
{/* Drawing polygons / rectangles / circles triggers the issue */}
Код: Выделить всё
useEffect(() => {
if (!map || !drawingLib) return;
const manager = new drawingLib.DrawingManager({
map,
// drawingMode: null,
// drawingControl: true,
drawingControlOptions: {
position: ControlPosition.TOP_RIGHT,
drawingModes: [
drawingLib.OverlayType.POLYGON,
drawingLib.OverlayType.RECTANGLE,
drawingLib.OverlayType.CIRCLE,
],
},
polygonOptions: {
fillColor: '#3388ff',
fillOpacity: 0.2,
strokeColor: '#3388ff',
strokeWeight: 3,
editable: false,
draggable: false,
clickable: true,
},
rectangleOptions: {
fillColor: '#3388ff',
fillOpacity: 0.2,
strokeColor: '#3388ff',
strokeWeight: 3,
editable: false,
draggable: false,
clickable: true,
},
circleOptions: {
fillColor: '#3388ff',
fillOpacity: 0.2,
strokeColor: '#3388ff',
strokeWeight: 3,
editable: false,
draggable: false,
clickable: true,
},
});
setDrawingManager(manager);
return () => {
manager.setMap(null);
};
}, [map, drawingLib]);
// 2. Handle Shape Creation
useEffect(() => {
if (!drawingManager) return;
const listener = window.google.maps.event.addListener(
drawingManager,
'overlaycomplete',
(event) => {
const overlay = event.overlay;
const type = event.type;
const id = Date.now() + Math.random();
let coords;
if (type === 'circle') {
coords = {
center: { lat: overlay.getCenter().lat(), lng: overlay.getCenter().lng() },
radius: overlay.getRadius(),
};
} else if (type === 'rectangle') {
const bounds = overlay.getBounds();
const ne = bounds.getNorthEast();
const sw = bounds.getSouthWest();
coords = [
{ lat: ne.lat(), lng: sw.lng() },
{ lat: ne.lat(), lng: ne.lng() },
{ lat: sw.lat(), lng: ne.lng() },
{ lat: sw.lat(), lng: sw.lng() },
];
} else {
// Polygon
const path = overlay.getPath().getArray();
coords = path.map((p) => ({ lat: p.lat(), lng: p.lng() }));
}
const newShape = {
id,
type: type.toLowerCase(),
coords,
[labelField.key]: '',
};
// Clear the drawing overlay immediately (we replace it with a managed one via state)
overlay.setMap(null);
drawingManager.setDrawingMode(null);
onShapeCreated(newShape);
onShapeSelectedForEdit(newShape);
},
);
return () => {
window.google.maps.event.removeListener(listener);
};
}, [drawingManager, onShapeCreated, onShapeSelectedForEdit, labelField.key]);
// 3. Sync State -> Google Maps Overlays
useEffect(() => {
if (!map || !drawingLib) return;
// Remove overlays not in state
overlaysRef.current.forEach((data, id) => {
const exists = shapes.find((s) => s.id === id);
if (!exists) {
data.overlay.setMap(null);
if (data.labelMarker) data.labelMarker.setMap(null);
window.google.maps.event.clearInstanceListeners(data.overlay);
overlaysRef.current.delete(id);
}
});
// Add or Update overlays
shapes.forEach((shape) => {
let data = overlaysRef.current.get(shape.id);
if (!data) {
let overlay;
const opts = {
map,
fillColor: '#3388ff',
fillOpacity: 0.2,
strokeColor: '#3388ff',
strokeWeight: 3,
editable: false,
draggable: false,
clickable: true,
zIndex: 1,
geodesic: false,
};
if (shape.type === 'circle') {
overlay = new window.google.maps.Circle({
...opts,
center: shape.coords.center,
radius: shape.coords.radius,
});
} else if (shape.type === 'rectangle') {
const bounds = new window.google.maps.LatLngBounds();
shape.coords.forEach((c) => bounds.extend(c));
overlay = new window.google.maps.Rectangle({ ...opts, bounds });
} else {
overlay = new window.google.maps.Polygon({
...opts,
paths: shape.coords,
});
}
// Click Listener
overlay.addListener('click', (e) => {
if (e.stop) e.stop();
onShapeClick({ id: shape.id });
});
// Edit Listeners
const triggerEdit = () => {
let newCoords;
if (shape.type === 'circle') {
newCoords = {
center: { lat: overlay.getCenter().lat(), lng: overlay.getCenter().lng() },
radius: overlay.getRadius(),
};
} else if (shape.type === 'rectangle') {
const b = overlay.getBounds();
const ne = b.getNorthEast();
const sw = b.getSouthWest();
newCoords = [
{ lat: ne.lat(), lng: sw.lng() },
{ lat: ne.lat(), lng: ne.lng() },
{ lat: sw.lat(), lng: ne.lng() },
{ lat: sw.lat(), lng: sw.lng() },
];
} else {
const path = overlay.getPath().getArray();
newCoords = path.map((p) => ({ lat: p.lat(), lng: p.lng() }));
}
onShapeEdited([{ id: shape.id, coords: newCoords }]);
};
if (shape.type === 'circle') {
overlay.addListener('radius_changed', triggerEdit);
overlay.addListener('center_changed', triggerEdit);
} else if (shape.type === 'rectangle') {
overlay.addListener('bounds_changed', triggerEdit);
} else {
const path = overlay.getPath();
['set_at', 'insert_at', 'remove_at'].forEach((evt) => {
window.google.maps.event.addListener(path, evt, triggerEdit);
});
}
// Label Marker
const labelMarker = new window.google.maps.Marker({
map,
position: getCenter(shape, overlay),
label: {
text: '',
color: 'white',
fontWeight: 'bold',
className: 'map-label-text',
},
icon: {
path: window.google.maps.SymbolPath.CIRCLE,
scale: 0,
},
zIndex: 1000,
});
data = { overlay, labelMarker };
overlaysRef.current.set(shape.id, data);
}
// Sync Label Content
const labelText = shape[labelField.key];
if (labelText) {
data.labelMarker.setLabel({
text: labelText,
color: '#FFFFFF',
fontWeight: 'bold',
fontSize: '14px',
});
data.labelMarker.setPosition(getCenter(shape, data.overlay));
data.labelMarker.setMap(map);
} else {
data.labelMarker.setMap(null);
}
});
}, [map, shapes, labelField.key, drawingLib, onShapeClick, onShapeEdited]);
// 4. Handle Selection Visuals
useEffect(() => {
overlaysRef.current.forEach((data, id) => {
const isSelected = selectedShape && id === selectedShape.id;
const { overlay } = data;
if (isSelected) {
overlay.setOptions({
fillColor: '#ff0000',
strokeColor: '#ff0000',
strokeWeight: 4,
fillOpacity: 0.3,
editable: true,
draggable: false,
});
} else {
overlay.setOptions({
fillColor: '#3388ff',
strokeColor: '#3388ff',
strokeWeight: 3,
fillOpacity: 0.2,
editable: false,
draggable: false,
});
}
});
}, [selectedShape]);
Подробнее здесь:
https://stackoverflow.com/questions/798 ... pes-in-vis
1765798603
Anonymous
Я использую [b]@vis.gl/react-google-maps[/b] с [b]библиотекой рисования Карт Google[/b] для рисования многоугольников, прямоугольников и кругов. Карта работает правильно, но [b]синие линии сетки (границы плиток/швы проекций)[/b] появляются [b]только при увеличении или уменьшении масштаба после рисования фигуры[/b]. Линии мигают во время масштабирования и выглядят следующим образом: Границы плиток отладки Google Maps. Важные наблюдения: [list] [*]Линии сетки [b]не появляются при начальной загрузке[/b] [*]Они [b]начинают появляться только после рисования многоугольников/прямоугольников/кругов[/b] [*]Удаление фигур [b]нет всегда удаляйте сетку[/b] [*]Проблема возникает только при [b]увеличении/уменьшении масштаба[/b] [/list] Я понимаю, что это, по-видимому, [b]внутренние плиточные/проекционные швы Google Maps[/b], которые становятся видимыми, когда карта переключается с растрового на векторный/WebGL рендеринг. Я попробовал следующее, [b]ничего не решило проблему[/b]: [list] [*]Удаление MapId [*]Отключение пользовательского интерфейса и элементов управления по умолчанию [*]Изменение обработки жестов [*]Принудительный растровый режим [*]Удаление DrawingManager [*]Изменения CSS/zIndex [code] {/* Drawing polygons / rectangles / circles triggers the issue */} [/code] [code] useEffect(() => { if (!map || !drawingLib) return; const manager = new drawingLib.DrawingManager({ map, // drawingMode: null, // drawingControl: true, drawingControlOptions: { position: ControlPosition.TOP_RIGHT, drawingModes: [ drawingLib.OverlayType.POLYGON, drawingLib.OverlayType.RECTANGLE, drawingLib.OverlayType.CIRCLE, ], }, polygonOptions: { fillColor: '#3388ff', fillOpacity: 0.2, strokeColor: '#3388ff', strokeWeight: 3, editable: false, draggable: false, clickable: true, }, rectangleOptions: { fillColor: '#3388ff', fillOpacity: 0.2, strokeColor: '#3388ff', strokeWeight: 3, editable: false, draggable: false, clickable: true, }, circleOptions: { fillColor: '#3388ff', fillOpacity: 0.2, strokeColor: '#3388ff', strokeWeight: 3, editable: false, draggable: false, clickable: true, }, }); setDrawingManager(manager); return () => { manager.setMap(null); }; }, [map, drawingLib]); // 2. Handle Shape Creation useEffect(() => { if (!drawingManager) return; const listener = window.google.maps.event.addListener( drawingManager, 'overlaycomplete', (event) => { const overlay = event.overlay; const type = event.type; const id = Date.now() + Math.random(); let coords; if (type === 'circle') { coords = { center: { lat: overlay.getCenter().lat(), lng: overlay.getCenter().lng() }, radius: overlay.getRadius(), }; } else if (type === 'rectangle') { const bounds = overlay.getBounds(); const ne = bounds.getNorthEast(); const sw = bounds.getSouthWest(); coords = [ { lat: ne.lat(), lng: sw.lng() }, { lat: ne.lat(), lng: ne.lng() }, { lat: sw.lat(), lng: ne.lng() }, { lat: sw.lat(), lng: sw.lng() }, ]; } else { // Polygon const path = overlay.getPath().getArray(); coords = path.map((p) => ({ lat: p.lat(), lng: p.lng() })); } const newShape = { id, type: type.toLowerCase(), coords, [labelField.key]: '', }; // Clear the drawing overlay immediately (we replace it with a managed one via state) overlay.setMap(null); drawingManager.setDrawingMode(null); onShapeCreated(newShape); onShapeSelectedForEdit(newShape); }, ); return () => { window.google.maps.event.removeListener(listener); }; }, [drawingManager, onShapeCreated, onShapeSelectedForEdit, labelField.key]); // 3. Sync State -> Google Maps Overlays useEffect(() => { if (!map || !drawingLib) return; // Remove overlays not in state overlaysRef.current.forEach((data, id) => { const exists = shapes.find((s) => s.id === id); if (!exists) { data.overlay.setMap(null); if (data.labelMarker) data.labelMarker.setMap(null); window.google.maps.event.clearInstanceListeners(data.overlay); overlaysRef.current.delete(id); } }); // Add or Update overlays shapes.forEach((shape) => { let data = overlaysRef.current.get(shape.id); if (!data) { let overlay; const opts = { map, fillColor: '#3388ff', fillOpacity: 0.2, strokeColor: '#3388ff', strokeWeight: 3, editable: false, draggable: false, clickable: true, zIndex: 1, geodesic: false, }; if (shape.type === 'circle') { overlay = new window.google.maps.Circle({ ...opts, center: shape.coords.center, radius: shape.coords.radius, }); } else if (shape.type === 'rectangle') { const bounds = new window.google.maps.LatLngBounds(); shape.coords.forEach((c) => bounds.extend(c)); overlay = new window.google.maps.Rectangle({ ...opts, bounds }); } else { overlay = new window.google.maps.Polygon({ ...opts, paths: shape.coords, }); } // Click Listener overlay.addListener('click', (e) => { if (e.stop) e.stop(); onShapeClick({ id: shape.id }); }); // Edit Listeners const triggerEdit = () => { let newCoords; if (shape.type === 'circle') { newCoords = { center: { lat: overlay.getCenter().lat(), lng: overlay.getCenter().lng() }, radius: overlay.getRadius(), }; } else if (shape.type === 'rectangle') { const b = overlay.getBounds(); const ne = b.getNorthEast(); const sw = b.getSouthWest(); newCoords = [ { lat: ne.lat(), lng: sw.lng() }, { lat: ne.lat(), lng: ne.lng() }, { lat: sw.lat(), lng: ne.lng() }, { lat: sw.lat(), lng: sw.lng() }, ]; } else { const path = overlay.getPath().getArray(); newCoords = path.map((p) => ({ lat: p.lat(), lng: p.lng() })); } onShapeEdited([{ id: shape.id, coords: newCoords }]); }; if (shape.type === 'circle') { overlay.addListener('radius_changed', triggerEdit); overlay.addListener('center_changed', triggerEdit); } else if (shape.type === 'rectangle') { overlay.addListener('bounds_changed', triggerEdit); } else { const path = overlay.getPath(); ['set_at', 'insert_at', 'remove_at'].forEach((evt) => { window.google.maps.event.addListener(path, evt, triggerEdit); }); } // Label Marker const labelMarker = new window.google.maps.Marker({ map, position: getCenter(shape, overlay), label: { text: '', color: 'white', fontWeight: 'bold', className: 'map-label-text', }, icon: { path: window.google.maps.SymbolPath.CIRCLE, scale: 0, }, zIndex: 1000, }); data = { overlay, labelMarker }; overlaysRef.current.set(shape.id, data); } // Sync Label Content const labelText = shape[labelField.key]; if (labelText) { data.labelMarker.setLabel({ text: labelText, color: '#FFFFFF', fontWeight: 'bold', fontSize: '14px', }); data.labelMarker.setPosition(getCenter(shape, data.overlay)); data.labelMarker.setMap(map); } else { data.labelMarker.setMap(null); } }); }, [map, shapes, labelField.key, drawingLib, onShapeClick, onShapeEdited]); // 4. Handle Selection Visuals useEffect(() => { overlaysRef.current.forEach((data, id) => { const isSelected = selectedShape && id === selectedShape.id; const { overlay } = data; if (isSelected) { overlay.setOptions({ fillColor: '#ff0000', strokeColor: '#ff0000', strokeWeight: 4, fillOpacity: 0.3, editable: true, draggable: false, }); } else { overlay.setOptions({ fillColor: '#3388ff', strokeColor: '#3388ff', strokeWeight: 3, fillOpacity: 0.2, editable: false, draggable: false, }); } }); }, [selectedShape]); [/code] [/list] Подробнее здесь: [url]https://stackoverflow.com/questions/79847635/blue-grid-tile-boundary-lines-appear-during-zoom-after-drawing-shapes-in-vis[/url]