не показываются балуны у меток
Я пытаюсь добавить свои метки с кастомными балунами, но проблема в том что сами метки добавляются, но балуны не открываются. Для своей реализации я использовал пример отсюда, но в нем реализовано с теги в самом .В моем случае эти маркера будут добавляться при нажатии на кнопку. Я не понимаю откуда он взял переменную index, и добавил это переменной key у Placemark, хотя в документацииэтого нет. Был бы рад любой подсказке. Спасибо. Вот мой способ вывода. Компонен УМар
import React, { useState,useEffect } from 'react';
import { YMaps, Map, Clusterer , Button,Placemark } from '@pbe/react-yandex-maps';
import InnerLayout from './InnerLayout';
import ReactDOMServer from 'react-dom/server';
const mapState = {
center: [55.7924886417031, 49.12233672582469],
zoom: 9
};
const YMap = () => {
const placemarkRef = React.useRef(null);
const mapRef = React.useRef(null);
const [canAddPlacemark, checkAddPlacemark] = useState(false);
const [ymaps, setYmaps] = useState(React.useRef(null));
const [openedDescription, openDescription] = useState(null);
const [clusterBalloon, setClusterBalloon] = useState(null);
const closeDescription = () => {
setClusterBalloon(null);
openDescription(null);
};
const createPlacemark = (coords) => {
return new ymaps.current.Placemark(
coords,
{
iconCaption: "loading.."
},
{
preset: "islands#violetDotIconWithCaption",
draggable: true
}
);
};
const getAddress = async (coords) => {
placemarkRef.current.properties.set("iconCaption", "loading..");
await ymaps.current.geocode(coords).then((res) => {
const firstGeoObject = res.geoObjects.get(0);
const newAddress = [
firstGeoObject.getLocalities().length
? firstGeoObject.getLocalities()
: firstGeoObject.getAdministrativeAreas(),
firstGeoObject.getThoroughfare() || firstGeoObject.getPremise()
]
.filter(Boolean)
.join(", ");
placemarkRef.current.properties.set({
iconCaption: newAddress,
balloonContent: ' <div> <input type="button" onClick={() => { openDescription(index);}} value="Подробнее"/> </div>'
});
regionName =firstGeoObject.getAdministrativeAreas()[0];
})
};
useEffect(() => {
if (document.getElementById('balloon') && clusterBalloon) {
ReactDOM.hydrate(
<InnerLayout
openDescription={openDescription}
openedDescription={openedDescription}
{...clusterBalloon}
/>,
document.getElementById('balloon'),
);
}
}, [clusterBalloon, openedDescription]);
const getLayout = (Component, props) => {
if (ymaps) {
const html = ReactDOMServer.renderToString(<Component {...props} />);
const Layout = ymaps.templateLayoutFactory.createClass(
`<div id="balloon">${html}</div>`,
{
build: function() {
Layout.superclass.build.call(this);
ReactDOM.hydrate(
<Component {...props} />,
document.getElementById('balloon'),
);
},
},
);
return Layout;
}
return null;
};
const openCluster = e => {
const cluster = e.get('cluster');
if (cluster) {
if (!clusterBalloon) {
setClusterBalloon(
cluster.state.get('activeObject').properties.getAll(),
);
}
cluster.state.events.add('change', () => {
const activeObject = cluster.state.get('activeObject');
console.log(activeObject.properties.getAll().index)
console.log(clusterBalloon.index)
if (
!clusterBalloon ||
(clusterBalloon &&
activeObject.properties.getAll().index !== clusterBalloon.index)
) {
setClusterBalloon(activeObject.properties.getAll());
}
});
}
};
const addMarkers = () =>{
let POINTS = [[55.79424260833246, 49.68814042729016],[55.62832515119459, 49.11135820072768],[55.910118447321, 48.70761064213393]]
for (let index = 0; index < POINTS.length; index++) {
const element = POINTS[index];
var clusterer = new ymaps.Clusterer({
preset: 'islands#invertedVioletClusterIcons',
groupByCoordinates: false,
balloonPanelMaxMapArea: Infinity,
clusterBalloonItemContentLayout: getLayout(InnerLayout, {
openedDescription,
openDescription,
...clusterBalloon,
}),
balloonopen:{openCluster},
balloonclose:{closeDescription}
})
var placemark = new ymaps.Placemark(
element,{
balloonContentHeader:"title"
}
, {
// Балун будем открывать и закрывать кликом по иконке метки.
hideIconOnBalloonOpen: false,
balloonContentLayout: getLayout(InnerLayout, {
element,
index,
openedDescription,
openDescription,
}),
balloonPanelMaxMapArea: Infinity,
}
);
clusterer.add(placemark)
mapRef.current.geoObjects.add(clusterer);
}
}
const onMapClick = (e) => {
if (canAddPlacemark){
let objectManager = new ymaps.current.ObjectManager();
objectManager.options.set('geoObjectInteractivityModel', 'default#transparent');
const coords = e.get("coords");
if (placemarkRef.current) {
placemarkRef.current.geometry.setCoordinates(coords);
} else {
placemarkRef.current = createPlacemark(coords);
mapRef.current.geoObjects.add(placemarkRef.current);
placemarkRef.current.events.add("dragend", function () {
getAddress(placemarkRef.current.geometry.getCoordinates());
});
}
getAddress(coords);
}
};
return (
<YMaps query={{
// load: "package.full" ,
apikey: "" }}>
<Map defaultState={{
center: [55.751574, 37.573856],
zoom: 9
}}
modules={["Clusterer","Polygon","GeoObject","geoQuery","control.ZoomControl", "control.FullscreenControl","Placemark", "geocode",
"geoObject.addon.balloon","borders", "ObjectManager",'geoObject.addon.balloon','clusterer.addon.balloon',
'templateLayoutFactory']}
style={{
flex: 2,
height: "calc(100vh - 57px)"
}}
onClick={onMapClick}
instanceRef={mapRef}
onLoad={ymaps => setYmaps(ymaps)}
state={mapState}
>
<Button onClick={addMarkers} data={{ content: 'Вывод маркеров' }} options={{ float: 'right' }} />
</Map>
</YMaps>
)
}
export default YMap;
Компонент для отображения содержимого балуна
import React from 'react';
const InnerLayout = ({ openedDescription, index, openDescription, point }) => {
if (openedDescription !== index) {
return (
<div>
<input
type="button"
onClick={() => {
openDescription(index);
}}
value="Подробнее"
/>
</div>
);
}
return <div>{"point.title"}</div>;
};
export default InnerLayout;