import React, { useEffect, useRef } from 'react';
import relgl from 'rel-gl';
import 'rel-gl/dist/rel-gl.css';
relgl.accessToken = 'your_api_key';
export default function Map() {
const mapContainer = useRef(null);
const map = useRef(null);
useEffect(() => {
if (map.current) return;
map.current = new relgl.Map({
container: mapContainer.current,
style: 'rel://api/styles/meringue_light_style.json',
center: [37.6165, 55.7505],
zoom: 10
});
return () => map.current.remove();
}, []);
return <div ref={mapContainer} style={{ width: '100%', height: '400px' }} />;
}
import React, { useEffect, useRef, useState } from 'react';
import relgl from 'rel-gl';
import 'rel-gl/dist/rel-gl.css';
relgl.accessToken = 'your_api_key';
export default function Map() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(37.6165);
const [lat, setLat] = useState(55.7505);
const [zoom, setZoom] = useState(10);
useEffect(() => {
if (map.current) return;
map.current = new relgl.Map({
container: mapContainer.current,
style: 'rel://api/styles/meringue_light_style.json',
center: [lng, lat],
zoom: zoom
});
map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
}, []);
return (
<div>
<div className="sidebar">
Lng: {lng} | Lat: {lat} | Zoom: {zoom}
</div>
<div ref={mapContainer} style={{ width: '100%', height: '400px' }} />
</div>
);
}
import React from 'react';
import relgl from 'rel-gl';
import 'rel-gl/dist/rel-gl.css';
relgl.accessToken = 'your_api_key';
class Map extends React.Component {
constructor(props) {
super(props);
this.state = {
lng: 37.6165,
lat: 55.7505,
zoom: 10
};
this.mapContainer = React.createRef();
}
componentDidMount() {
const { lng, lat, zoom } = this.state;
this.map = new relgl.Map({
container: this.mapContainer.current,
style: 'rel://api/styles/meringue_light_style.json',
center: [lng, lat],
zoom: zoom
});
this.map.on('move', () => {
this.setState({
lng: this.map.getCenter().lng.toFixed(4),
lat: this.map.getCenter().lat.toFixed(4),
zoom: this.map.getZoom().toFixed(2)
});
});
}
componentWillUnmount() {
this.map.remove();
}
render() {
const { lng, lat, zoom } = this.state;
return (
<div>
<div className="sidebar">
Lng: {lng} | Lat: {lat} | Zoom: {zoom}
</div>
<div ref={this.mapContainer} style={{ width: '100%', height: '400px' }} />
</div>
);
}
}
export default Map;
import React, { useEffect, useRef, useState } from 'react';
import relgl from 'rel-gl';
import 'rel-gl/dist/rel-gl.css';
relgl.accessToken = 'your_api_key';
export default function MapWithSidebar() {
const mapContainer = useRef(null);
const map = useRef(null);
const [activeFeature, setActiveFeature] = useState(null);
useEffect(() => {
if (map.current) return;
map.current = new relgl.Map({
container: mapContainer.current,
style: 'rel://api/styles/meringue_light_style.json',
center: [37.6165, 55.7505],
zoom: 10
});
map.current.on('load', () => {
map.current.addSource('places', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: { name: 'Москва', description: 'Столица России' },
geometry: { type: 'Point', coordinates: [37.6165, 55.7505] }
}
]
}
});
map.current.addLayer({
id: 'places',
type: 'circle',
source: 'places',
paint: {
'circle-radius': 8,
'circle-color': '#0078d4'
}
});
map.current.on('click', 'places', (e) => {
setActiveFeature(e.features[0].properties);
});
map.current.on('mouseenter', 'places', () => {
map.current.getCanvas().style.cursor = 'pointer';
});
map.current.on('mouseleave', 'places', () => {
map.current.getCanvas().style.cursor = '';
});
});
return () => map.current.remove();
}, []);
return (
<div style={{ display: 'flex', height: '400px' }}>
<div style={{ width: '300px', padding: '16px', overflowY: 'auto' }}>
{activeFeature ? (
<>
<h3>{activeFeature.name}</h3>
<p>{activeFeature.description}</p>
</>
) : (
<p>Нажмите на объект для просмотра информации</p>
)}
</div>
<div ref={mapContainer} style={{ flex: 1 }} />
</div>
);
}