I'm facing with a problem that I can't get my current location by react-leaflet v4.0.1 and react v18.2.0 when the project has been deployed on IIS.
I Just can get the current location when node js is running on localhost/register but not on domain example.com/register.
maybe its CROS origin problem but I dont know how to handle it by domain
name.
it workes well:
but it has problem with domain:
in Map.js
import React, { useEffect, useState } from 'react'
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import L from 'leaflet'
import icon from './constants'
export default function App() {
function LocationMarker() {
const [position, setPosition] = useState(null)
const [bbox, setBbox] = useState([])
const map = useMap()
useEffect(() => {
map.locate().on('locationfound', function (e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
setBbox(e.bounds.toBBoxString().split(','))
})
}, [map])
return position === null ? null : (
<Marker position={position} icon={icon}>
<Popup>
You are here. <br />
Map bbox: <br />
<b>Southwest lng</b>: {bbox[0]} <br />
<b>Southwest lat</b>: {bbox[1]} <br />
<b>Northeast lng</b>: {bbox[2]} <br />
<b>Northeast lat</b>: {bbox[3]}
</Popup>
</Marker>
)
}
return (
<MapContainer
center={[35.1951, 51.6068]}
zoom={13}
scrollWheelZoom
style={{ height: '50vh' }}
>
<div style={{ height: '50vh' }}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<LocationMarker />
</div>
</MapContainer>
)
}
Related
I have a video on my site that I want to be paused when I scroll it and play only when its visible. I have tried some solutions from internet but things are not working out.
This is my current code. I have tried out a solution from stackoverflow which shows me observe error. I would be glad if someone helps me out on this. Thank you.
Player.js
import { Box, Container } from "#mui/system";
import React, { useEffect, useRef, useState } from "react";
import ReactPlayer from "react-player";
import styled from "styled-components";
import videosample from "./homepagevideo.mp4";
const ResponsiveStyledPlayer = () => {
const Player = ({ className }) => (
<ReactPlayer
url={videosample}
className={className}
playing={true}
autoplay={true}
width="100%"
height="100%"
controls={false}
muted
loop={true}]
/>
);
const AbsolutelyPositionedPlayer = styled(Player)`
position: absolute;
top: 0;
left: 0;
`;
const RelativePositionWrapper = styled.div`
position: relative;
padding-top: 56.25%;
`;
return (
<Box>
<Container>
<RelativePositionWrapper>
<AbsolutelyPositionedPlayer />
</RelativePositionWrapper>
</Container>
</Box>
)
};
export default ResponsiveStyledPlayer;
you can you Waypoint for your requirement. I have made one demo for you, you can refer to that. Link Demo
import React, { useState } from 'react';
import ReactPlayer from 'react-player/youtube';
import { Waypoint } from 'react-waypoint';
import './style.css';
export default function App() {
let [shouldPlay, updatePlayState] = useState(false);
let handleEnterViewport = function () {
updatePlayState(true);
};
let handleExitViewport = function () {
updatePlayState(false);
};
return (
<div>
<Waypoint onEnter={handleEnterViewport} onLeave={handleExitViewport}>
<div>
<ReactPlayer
playing={shouldPlay}
url="https://www.youtube.com/watch?v=ysz5S6PUM-U"
/>
</div>
</Waypoint>
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
<h1>hii</h1>
<br />
</div>
);
}
I'm trying to link the list with the leaflet map. I want to click on a result card and see the marker on the map. I'm using fake data for now in json format. I would like a display like airbnb, list plus display the list on map.
This is the map file :
import React, { useState } from "react";
import { Map, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { Icon } from "leaflet";
import FakeData from "../../../../../../data";
import {Div, PopContainer} from "./style"
const MarkerIcon = new Icon({
iconUrl: "../public/markerIcon.png",
iconSize: [50, 50],
});
function MapBox() {
const [nurse, setNurse] = useState(null);
const bull = <span>•</span>;
return (
<Div>
<Map center={[50.6365654, 3.0635282]} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
/>
{FakeData.map((data) => (
<Marker
key={data.id}
icon={MarkerIcon}
position={[data.coordonatelat, data.coordonatelng]}
onmouseover={() => {
setNurse(data);
}}
/>
))}
{nurse && (
<Popup
position={[nurse.coordonatelat, nurse.coordonatelng]}
onClose={() => {
setNurse(null);
}}
>
<PopContainer>
<h2>
{bull}
{nurse.first_name} {nurse.last_name}
{bull}
</h2>
<h3>
{nurse.job}
</h3>
<p> {nurse.address}
<br />
{nurse.phone_number}
</p>
</PopContainer>
</Popup>
)}
</Map>
</Div>
);
}
export default MapBox;
This is the resultPage :
import React from "react";
import FakeData from "../../../../../../data";
import MapBox from "../map/index";
import { Scrollbars } from "react-custom-scrollbars";
import {
Container,
H1,
Card,
CardContent,
H2,
Address,
Phone,
NavLink,
CardActions,
Job,
MapContainer,
BigContainer,
CardContainer,
Box,
Li,
} from "./resultPageStyle";
function Result(props) {
const bull = <span>•</span>;
return (
<BigContainer>
<Container>
<H1>Résultats</H1>
<Box>
<Scrollbars style={{ width: 650, height: 580 }}>
<CardContainer>
{FakeData.slice(0, 30).map((item) => (
<Li key={item.id}>
<Card>
<CardContent>
<Job>{item.job}</Job>
<H2>
{bull}
{item.first_name} {item.last_name}
{bull}
</H2>
<Address>{item.address}</Address>
<Phone>{item.phone_number}</Phone>
</CardContent>
<CardActions>
<NavLink to={"/detailsPage"}>Plus d'infos</NavLink>
</CardActions>
</Card>
</Li>
))}
</CardContainer>
</Scrollbars>
<MapContainer>
<MapBox />
</MapContainer>
</Box>
</Container>
</BigContainer>
);
}
export default Result;
I tried diferent thing but it is not working.
Create a state variable on Result comp to keep track of the card item that holds the lat lng info
Pass it as a prop to Mapbox comp
On the Mapbox comp create a local variable to save the map instance and use it to change the map view every time you click on a card.
divider
function Result() {
const bull = <span>•</span>;
const [cardItem, setCardItem] = useState(null);
const handleCardClick = (item) => {
console.log(item);
setCardItem(item);
};
...
<Card onClick={() => handleCardClick(item)}>
...
<MapContainer>
<MapBox cardItem={cardItem} />
</MapContainer>
}
divider
function MapBox({ cardItem }) {
const [nurse, setNurse] = useState(null);
const bull = <span>•</span>;
const [map, setMap] = useState(null);
useEffect(() => {
if (!cardItem || !map) return;
const { coordonatelat, coordonatelng } = cardItem;
map.setView([coordonatelat, coordonatelng], 13);
}, [cardItem, map]);
...
}
I fixed also your demo issues and added a cursor when you hover on each card.
You can use also map.flyTo which gives a nice animation out of the box instead of map.setView. It's up to you.
Demo
So basically I was able to get a database which stores points in it.
Now I was able to push each point separately to make this database. Now I need to display these points on the map. This is my code so far:
App.js
import './App.css';
import * as React from "react";
import firebase from "./firebase";
import { ChakraProvider } from "#chakra-ui/react";
import { MapContainer, TileLayer, Marker, Popup, useMapEvents, useMap } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import * as L from 'leaflet';
import SearchBar from './SearchBar';
import CovidPoint from './CovidPoint';
import LocationMarkers from './LocationMarkers';
class App extends React.Component {
constructor(props){
super(props)
this.state = {
map: null,
points: [<CovidPoint
position={[43.653226, -79.3831843]}
name="point1"
information="random point"
input = {false}
></CovidPoint>]
}
}
changePos = (pos, zoom) => {
const {map} = this.state;
if (map) map.flyTo(pos, zoom);
}
fetchPoints = (newPoints) => {
// fetch info from database
const ref = firebase.database().ref("points")
const pointsref = ref.push()
pointsref.set(newPoints)
this.setState({points: newPoints})
}
componentDidMount() {
const ref = firebase.database().ref("points")
ref.on("value", snapshot => {
console.log("FireB ",snapshot)
if (snapshot && snapshot.exists()) {
this.setState({points: snapshot.val})
}})
console.log("page loaded!")
}
render() {
return (
<div className="App">
<div id="title">
<h1>CovidStopSpots</h1>
<p>A responsive tracker for Covid-19.</p>
</div>
<div id="map">
<MapContainer
id="1"
center={[43.653226, -79.3831843]}
zoom={13}
scrollWheelZoom={false}
whenCreated={(map) => this.setState({ map })}
style={{ height: "100vh " }}
>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{this.state.points.length > 0 && this.state.points.map(
(point, index) => {
<li key={index}></li>
return point
}) }
{/* <CovidPoint
position={[43.653226, -79.3831843]}
name="point1"
information="random point"
></CovidPoint>
<CovidPoint
position={[50.653226, -79.3831843]}
name="point2"
information="random point"
></CovidPoint> */}
<LocationMarkers points={this.state.points} fetchPoints={this.fetchPoints}></LocationMarkers>
<div id="searchbar">
<SearchBar changePos={this.changePos}/>
</div>
</MapContainer>
</div>
</div>
);
}
}
export default App;
The location Marker file which basically "plots" the points and pushes the to the database.
LocationMarker.js
import { useState } from "react";
import { useMapEvents } from "react-leaflet";
import CovidPoint from "./CovidPoint";
function LocationMarkers(props) {
const [position, setPosition] = useState([]);
useMapEvents({
dblclick(ev) {
console.log("double clicked");
const { lat, lng } = ev.latlng;
setPosition([lat, lng]);
const newPoints = [...props.points];
console.log(newPoints);
newPoints.push(<CovidPoint
position={[lat, lng]}
name="test"
information="test"
input = {true}
></CovidPoint>);
props.fetchPoints(newPoints);
}
});
return null;
}
export default LocationMarkers;
As you can see on this example from documentation, you should use Marker to place a marker. Assuming that you have an array of points (list of coordinates), you can place a list of points like this:
const position = [
[51.505, -0.09],
[51.510, -0.09],
[51.515, -0.09]
]
render(
<MapContainer center={position} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{points?.map((point)=>(
<Marker position={point}>
)}
</Marker>
</MapContainer>,
)
I don't know what is this CovidPoint. But I think you dont need it.
React-leaflet when i introduce a drop down menu at top, its hidden behind the map when i drop it down. Any help will be appreciated. Below is a screen shoot of how its rendering on my front
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css'
const position = [-0.29008, 3.81987]
class App extends Component {
render() {
return (
<div>
<div className='form-row'>
<div className='form-group col-md-12'>
<Select
placeholder='Search a single Fleet'
options={[{ value: 'clear', label: 'Clear Search' }, ...options]}
key={'show'}
onChange={(e) => {
if (e.value === 'clear') setTheVehicle(undefined)
else setTheVehicle(e.value)
}}
/>
</div>
</div>
<Map center={position} zoom={13}>
<TileLayer
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
attribution='© OpenStreetMap contributors'
/>
<Marker position={this.state.center}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</Map>
</div>
);
}
}
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Rather little lazy answer but took me ages :
Check new style on first <div>
<div className='form-row' style={{position: 'relative', z-index: 999}}>
<div className='form-group col-md-12'>
<Select
placeholder='Search a single Fleet'
options={[{ value: 'clear', label: 'Clear Search' }, ...options]}
key={'show'}
onChange={(e) => {
if (e.value === 'clear') setTheVehicle(undefined)
else setTheVehicle(e.value)
}}
/>
</div>
</div>
Actually, I am using react-leaflet with custom popup, when i tried to use react-router-dom Link component in it than i got error
"leaflet": "^1.4.0",
"leaflet.markercluster": "^1.3.1",
"react": "^16.5.2",
"react-dom": "^16.8.4",
"react-router-dom": "4.3.1",
"react-router-redux": "5.0.0-alpha.9",
React Router Link doesn't work with LeafletJS
I tried above mentioned link but still got error.
*
* CustomPopup
*
*/
import React from 'react';
import Moment from 'moment';
import {extendMoment} from "moment-range";
import {Link, withRouter} from "react-router-dom";
import currencyFormatter from "../../utils/currencyFormatter";
const moment = extendMoment(Moment);
const CustomPopup = (props) => {
const { item } = props;
return (
<div className='map-properties'>
<div className='map-img'>
<img
style={{width: "301px", height: "203px"}}
src={item.image ? `${item.image}`: "http://placehold.it/301x203"}
className="custom-img"
onError={(e)=>{e.target.onerror = null; e.target.src="http://placehold.it/301x203"}}
/>
</div>
<div className='map-content'>
<h4><a href='properties-details.html'> {item.title} </a></h4>
{item.address && <p className='address'> <i className='fa fa-map-marker'></i> {item.address} </p>}
<p className='description'> description </p>
<div className='map-properties-fetures'>
<span><i className='flaticon-square-layouting-with-black-square-in-east-area'></i>{item.area} sqft<sup>2</sup></span>
<span className="right"><i className='flaticon-bed'></i>{item.bedrooms}</span>
<span><i className='flaticon-holidays'></i>{item.bathrooms}</span>
<span className="right">
<i className="fa fa-calendar"></i> {moment.range(moment(item.created_at), moment()).diff('days')} Days ago
</span>
</div>
<div className='map-properties-btns'>
<a className='border-button-sm border-button-theme' style={{marginRight: "5px"}}>
{currencyFormatter(item.price)}
</a>
##below the React Router Dom component <Link/>##
<Link href='properties-details' className='button-sm button- theme'>Details</Link>
</div>
</div>
</div>
);
};
export default CustomPopup;
/**
*
*End of CustomPopup
*
*/
/**
*
* LeafLet Map Container where i use above custom popup
*
*/
import "./index.css";
import React, {Fragment, PropTypes } from 'react';
import CustomPopup from "../../components/CustomPopup";
import {createClusterCustomIcon, ThemePointer} from "../../components/CustomMarker";
import 'react-leaflet-markercluster/dist/styles.min.css';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import {TileLayer, Marker, Popup, Map, LayersControl,} from 'react-leaflet';
import {withRouter} from "react-router-dom";
import ContextProvider from "../../components/ContextProvider";
export const Context = React.createContext({});
const MyPopupMarker = (props) => {
const { item } = props;
let lat = item.latitude ? item.latitude : 0.0000;
let lng = item.longitude ? item.longitude : 0.0000;
return (
<Marker position={[lat, lng]} icon={ThemePointer}>
<Popup>
<CustomPopup key={item.id} item={item} />
</Popup>
</Marker>
);
};
const MyMarkersList = (props) => {
const { markers } = props;
const items = markers && markers.length > 0 ? markers.map((item, index) => (
<MyPopupMarker key={item.id} item={item} context={props.context}/>
)): "";
return <Fragment>{items ? items : ""}</Fragment>;
};
const { BaseLayer,} = LayersControl;
class LeafLetMap extends React.PureComponent{
updateDimensions() {
const height = window.innerWidth >= 992 ? window.innerHeight : 400
this.setState({ height: height - 348 })
}
componentWillMount() {
this.updateDimensions()
}
componentDidMount() {
window.addEventListener("resize", this.updateDimensions.bind(this))
console.log(this.props.context)
}
componentWillUnmount() {
this._isMounted = false;
window.removeEventListener("resize", this.updateDimensions.bind(this))
}
render(){
const {filterPropertiesList, featuredPropertyList} = this.props;
let markers;
if(!filterPropertiesList.isSearched && featuredPropertyList.data.length > 0){
markers = featuredPropertyList.data;
}else if(filterPropertiesList.isSearched && filterPropertiesList.data.properties.length > 0){
markers = filterPropertiesList.data.properties;
}
return (
<Map style={{ height: this.state.height }} center={[25.0657, 55.17128]} zoom={16}>
<LayersControl position="bottomleft">
<BaseLayer checked name="Default">
<TileLayer
attribution='© OpenStreetMap contributors'
url="http://{s}.google.com/vt/lyrs=p&x={x}&y={y}&z={z}"
subdomains={['mt0','mt1','mt2','mt3']}
/>
</BaseLayer>
<BaseLayer name="Satellite">
<TileLayer
attribution='© OpenStreetMap contributors'
url="http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}"
subdomains={['mt0','mt1','mt2','mt3']}
/>
</BaseLayer>
</LayersControl>
<MarkerClusterGroup iconCreateFunction={createClusterCustomIcon}>
<MyMarkersList markers={markers} />
</MarkerClusterGroup>
</Map>
);
}
}
export default LeafLetMap;
Warning: Failed prop type: The prop to is marked as required in Link, but its value is undefined.
Warning: Failed context type: The context router is marked as
required in Link, but its value is undefined.
I mentioned libraries versions, post container and custom popup where i used react router dom link component.
I also paste occurred warnings as a results.