Marker position on the map Leaflet - javascript

I have a custom map created using the Leaflet library. And also the Marker component. When I place a marker with a value of 100 on the Y-axis, the marker is at the top of the map, but when I place a marker on the Y-axis of 50, the marker is not in the middle of the map. Same thing with the X-axis. How can I find the exact coordinates of the map, what can I do to position the marker according to the coordinates passed from the backend?
Code from component App
import "./styles.css";
import { MapContainer, ImageOverlay } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import Marker from "./Marker";
const M = ({ width, height, zoom, center }) => {
const wh = [width, 500];
const origin = [0, 0];
const bounds = [origin, wh];
return (
<div style={{ width: "1100px", height: "600px" }}>
<MapContainer
style={{ height: "100%", minHeight: "100%" }}
bounds={zoom ? undefined : bounds}
boundsOptions={{
padding: [0, 0]
}}
maxBounds={bounds}
zoom={center ? zoom : undefined}
center={zoom ? center : undefined}
>
<ImageOverlay
url="../ptichnikDraw.png"
bounds={bounds}
className="map_main"
/>
<Marker />
</MapContainer>
</div>
);
};
const App = () => {
return (
<div
style={{
display: "flex",
justifyContent: "center"
}}
>
<M width={1500} height={500} center={[0, 0]} />
</div>
);
};
export default App;
Code from component Marker
import { LeafletTrackingMarker } from "react-leaflet-tracking-marker";
import L from "leaflet";
import { Popup } from "react-leaflet";
const icon = L.icon({
iconSize: [35, 35],
popupAnchor: [2, -20],
iconUrl: require("../public/marker_map.png")
});
export default function Marker() {
return (
<>
<LeafletTrackingMarker
icon={icon}
position={[50, 450]} // changing the position of the marker
duration={10}
></LeafletTrackingMarker>
</>
);
}
Link to full code: https://codesandbox.io/s/dark-worker-8qbzfr?file=/src/Marker.jsx

Related

How to move BasemapGallery position in ReactJS Leaflet?

I want to move the position in the Basemap Gallery Leaflet to the top near the Leaflet zoom on the Map but am confused about how to move the coding, here it is:
Basemap Gallery Brochure wants to move up and near Zoom.
Sample image: Images
Example of desired Basemap Gallery position:
Example of Basemap Gallery position
Here is my code and what I need to change in my code:
import { React, useState, useEffect } from 'react'
import {
LayersControl,
MapContainer,
TileLayer,
Marker,
Popup,
useMapEvents,
} from 'react-leaflet'
import List from '../Component/List'
import L from 'leaflet'
import SearchControl from './SearchControl'
const { BaseLayer } = LayersControl
function LocationMarker() {
const [position, setPosition] = useState(null)
const map = useMapEvents({
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})
return position === null ? null : (
<Marker position={position}>
<Popup>Location Me</Popup>
</Marker>
)
}
function MyLocationMe() {
const [map, setMap] = useState(null)
const [position, setPosition] = useState(null)
useEffect(() => {
if (!map) return
L.easyButton('fa-map-marker', () => {
map.locate().on('locationfound', function (e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
})
}).addTo(map)
}, [map])
return (
<div className="flex ml-auto">
<List />
<div className="w-4/5">
<MapContainer
center={{ lat: 51.505, lng: -0.09 }}
zoom={20}
style={{ height: '100vh' }}
whenCreated={setMap}
>
<SearchControl className="MarkerIcon" position="topright" />
<LayersControl position="topleft">
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
<LocationMarker />
</MapContainer>
</div>
</div>
)
}
export default MyLocationMe
The easiest way to do that is to change the left css property of the relevant css class by making position absolute
Add this to your styles.css
.leaflet-control-layers.leaflet-control {
position: absolute;
left: 50px;
}
Demo

When creating a Marker onClick, the marker is offset and not directly where the mouse cursor is

I'm trying to create a react-leaflet Map that onClick creates a Marker on the click's Lat and Lng. The problem is that the marker is created at an offset, towards the bottom right instead of on the mouse cursor.
import React, { useState, useContext } from "react";
import classes from "./WorldMap.module.css";
import { Map, TileLayer, Marker } from "react-leaflet";
import L from "leaflet";
import RoundInformationDisplay from "./RoundInfoDisplay/RoundInfoDisplay";
import ConfirmGuessButton from "./ConfirmGuessButton/ConfirmGuessButton";
import { AppContext } from "../../../../context/appContext";
interface Props {
handleEndOfRound: () => void;
}
const WorldMap: React.FC<Props> = (props) => {
const { currentRoundGuess, setCurrentRoundGuess } = useContext(AppContext);
const icon = L.icon({ iconUrl: require("../../../../static/marker.svg") });
const [selected, setSelected] = useState<boolean>(false);
const handleMapClick = (e: any) => {
setCurrentRoundGuess({ ...e.latlng });
setSelected(true);
};
return (
<div className={classes.WorldMapContainer}>
<div className={classes.InfoDisplay}>
<RoundInformationDisplay />
</div>
<Map
center={[45.4, -75.7]}
zoom={3}
className={classes.Map}
onClick={(e: any) => handleMapClick(e)}
>
{selected ? (
<Marker
position={[currentRoundGuess.lat, currentRoundGuess.lng]}
icon={icon}
/>
) : (
<p></p>
)}
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
</Map>
<div className={classes.ConfirmButton}>
<ConfirmGuessButton
selected={selected}
handleEndOfRound={props.handleEndOfRound}
/>
</div>
</div>
);
};
export default WorldMap;
A video showcasing the issue: https://streamable.com/g5uusl
What could be causing this problem? Thank you in advance.
As was mentioned in comments icon.iconanchor property allows to align the icon position relative to marker's location, in case of react-leaflet library, icon.iconanchor property could be specified as demonstrated below:
function MapExample(props) {
const [selectedPos, setSelectedPos] = useState(props.center);
function getMarkerIcon() {
const icon = new L.Icon({
iconSize: [32, 37], // size of the icon
iconAnchor: [16, 37],
iconUrl: "/bigcity_green.png",
});
return icon;
}
function handleMapClick(e) {
setSelectedPos(e.latlng);
}
return (
<Map center={props.center} zoom={props.zoom} onclick={handleMapClick}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{selectedPos && <Marker position={selectedPos} icon={getMarkerIcon()} />}
</Map>
);
}

Showing full map on smaller screens in Material UI

I am trying to make my app responsive for smaller screens. On bigger screens, I have the <List> buttons for large screens but when the screen size is xs(mobile), I want that the whole screen should be covered with the map. I am able to hide the list in smaller screens but since I am using map width to be 80% the sm screens only cover 80% for the map and 20% is just white screen. How can I bring the map to 100% on sm screen
...
import React from "react";
import { List, ListItem } from "#material-ui/core";
import { Map, Marker, Popup, TileLayer } from "react-leaflet";
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import "./styles.css";
import Icon from "../src/icon.png";
import shadow from "../src/shadow.png";
import Hidden from "#material-ui/core/Hidden";
export default class App extends React.Component {
constructor() {
super();
this.state = {
location: [
{
id: 1,
machine: 1,
lat: 51.503,
lng: -0.091
},
{
id: 2,
machine: 2,
lat: 51.543,
lng: -0.051
}
],
center: [51.505, -0.091],
zoom: 11,
marker: null
};
this.clickAction = this.clickAction.bind(this);
}
Icon = L.icon({
iconUrl: Icon,
shadowUrl: shadow,
iconSize: [38, 50],
shadowSize: [50, 64],
iconAnchor: [22, 34], // point of the icon which will correspond to marker's location
shadowAnchor: [4, 62],
popupAnchor: [-3, -76] // point from which the popup should open relative to the iconAnchor
});
openPopUp(marker, id) {
if (marker && marker.leafletElement) {
marker.leafletElement.openPopup(id);
}
}
clickAction(id, lat, lng) {
this.setState({ marker: id, zoom: 16, center: [lat, lng] });
}
render() {
console.log(this.state);
return (
<>
<Map center={this.state.center} zoom={this.state.zoom}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
{this.state.location &&
this.state.location.map(location => {
return location !== null ? (
<Marker
position={[location?.lat, location?.lng]}
icon={this.Icon}
ref={this.openPopUp(location?.id)}
>
<Popup> {location?.id} </Popup>
</Marker>
) : null;
})}
</Map>
{
<Hidden smDown>
<List style={{ width: "20%", float: "left" }}>
{this.state.location &&
this.state.location.map(({ id, machine, lat, lng }) => {
return (
<ListItem
key={id}
button
onClick={() => {
this.clickAction(id, lat, lng);
}}
>
Id {id} <br />
machine {machine}
</ListItem>
);
})}
</List>
</Hidden>
}
</>
);
}
}
}
...
my sample is https://codesandbox.io/s/gallant-star-m42qe?file=/src/App.js

ReactJs Leaflet Marker Location Position Problem

I am trying to add a map in my reactjs project with leaflet and want to show the location's of vehicles on the map. I made a sample usage for this. But When i used marker on the map i see that (as you can see in this image):
marker's left top side stick to my location. I want to see marker's bottom on the center of my location as the circle is. But i could not do it. I read react-leaflet documentation but did not see a parameter for this. If you help me, I appreciate for this. Thanks
import React, { Component } from 'react'
import Leaflet from 'leaflet';
import { Map, CircleMarker, TileLayer, Marker, Popup } from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';
let DefaultIcon = Leaflet.icon({
iconUrl: icon,
shadowUrl: iconShadow
});
Leaflet.Marker.prototype.options.icon = DefaultIcon;
class SimpleExample extends React.Component {
constructor(props) {
super();
this.state = {
lat: 39.9653301,
lng: 32.7760817,
zoom: 5,
markerPoint: {
x: 320,
y: 192
}
};
this.refMap = React.createRef();
}
render() {
const { lat, lng, zoom } = this.state;
const position = [lat, lng];
return (
<Map ref={this.refMap} center={position} zoom={zoom} style={{ height: '400px', width: '100%' }}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={position} draggable="True" pane="popupPane" >
</Marker>
<CircleMarker
center={position}
color='green'
fillColor='red'
radius={20}
fillOpacity={0.5}
stroke={false}
>
<Popup>
<span>A pretty CSS3 popup. <br/> Easily customizable.</span>
</Popup>
</CircleMarker>
</Map>
);
}
}
export default SimpleExample;
Define proper iconAnchor size and marker will be placed on the correct location.
let DefaultIcon = Leaflet.icon({
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40],
iconUrl: icon,
shadowUrl: iconShadow
});
Demo

react-leaflet-rotatedmarkers: TypeError: Super expression must either be null or a function, not object

as you can see in the topic is my problem that when i want to import react-leaflet-rotatedmarker, only importing, my react webapplication throws me this message.
I'm using react-leaflet v2.1.2.
Here is a snippet of my js code:
import React, { Component } from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import L, { map, addTo } from 'leaflet';
import RotatedMarker from 'react-leaflet-rotatedmarker'
import './App.css'
//importing marker/icon
var ego_veh_icon = L.icon({
iconUrl: require('./design/icons/ego_veh_arrow.svg'),
iconSize: [150, 200],
iconAnchor: [82.5, 40],
popupAnchor: [0, -25],
});
var av_veh_icon = L.icon({
iconUrl: require('./design/icons/autonom_veh_arrow.svg'),
iconSize: [150, 200],
iconAnchor: [82.5,55],
popupAnchor: [-5, -25],
});
var nav_veh_icon = L.icon({
iconUrl: require('./design/icons/non_autonom_veh_arrow.svg'),
iconSize: [150, 200],
iconAnchor: [82.5, 60],
popupAnchor: [-10, -25],
});
class Map_hmi extends Component {
constructor() {
super();
this.state = {
markers: [[x, y]],
param: null,
};
}
// ego veh position
ego_veh = {
lat: x,
lng: y,
}
// nav veh position
nav_veh = {
lat: x,
lng: y,
}
// av veh1 position
av_veh1 = {
lat: x,
lng: y,
}
// av veh2 position
av_veh2 = {
lat: x
lng: y,
}
render() {
const ego_veh_pos = [this.ego_veh.lat, this.ego_veh.lng]
const nav_veh_pos = [this.nav_veh.lat, this.nav_veh.lng]
const av_veh1_pos = [this.av_veh1.lat, this.av_veh1.lng]
const av_veh2_pos = [this.av_veh2.lat, this.av_veh2.lng]
return (
// declaring the map
<Map
className="map"
center={ego_veh_pos}
zoom={15}
zoomControl={false}
>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{/* <RotatedMarker position={position} rotationAngle={180} rotationOrigin={'center'} /> */}
{/* ego veh */}
<Marker
position={ego_veh_pos}
icon= {ego_veh_icon}>
<Popup>
EGO <br/>
</Popup>
</Marker>
{/* nav veh */}
<Marker
position={nav_veh_pos}
icon= {nav_veh_icon}>
<Popup>
NAV <br/>
</Popup>
</Marker>
{/* av veh1 */}
<Marker
position={av_veh1_pos}
icon= {av_veh_icon}>
<Popup>
AV <br/>
</Popup>
</Marker>
{/* av veh2 */}
<Marker
position={av_veh2_pos}
icon= {av_veh_icon}>
<Popup>
AV <br/>
</Popup>
</Marker>
)}
</Map>
);
}
}
export default Map_hmi;
So my code works fine without the import, but as soon as I import it:
TypeError: Super expression must either be null or a function, not object
I only want to rotate the icon ....
Any help?
Greetings
The provided another answer seems to be correct, react-leaflet-rotatedmarker package is not compatible with react-leaflet v2 package.
For react-leaflet v2 library, RotatedMarker component could be implemented like this (offers same behavior as react-leaflet-rotatedmarker package):
import React, { Component } from "react";
import { withLeaflet } from "react-leaflet";
import { Marker } from "react-leaflet";
import { Marker as LeafletMarker } from 'leaflet-rotatedmarker';
const RotatedMarker = props => {
const setupMarker = marker => {
if (marker) {
if (props.rotationAngle)
marker.leafletElement.setRotationAngle(props.rotationAngle);
marker.leafletElement.setRotationOrigin(props.rotationOrigin);
}
};
return <Marker ref={el => setupMarker(el)} {...props} />;
};
RotatedMarker.defaultProps = {
rotationOrigin: "center"
};
export default withLeaflet(RotatedMarker);
Demo page
tldr: Using the code in this comment should fix your problem. https://github.com/verdie-g/react-leaflet-rotatedmarker/issues/1#issuecomment-427285940
Longer answer:
react-leaflet v2 has a very major breaking change from v1 in the way extensions of components are done. If you look at the code for react-leaflet-rotatedmarker you'll see this line: https://github.com/verdie-g/react-leaflet-rotatedmarker/blob/master/src/RotatedMarker.jsx#L5
That extension of the Marker class does not work in v2 and is what's throwing that error. For more info on why that is you can check out the issue I raised in the react-leaflet repo. https://github.com/PaulLeCam/react-leaflet/issues/506

Categories

Resources