how to use react-leaflet with preact - leaflet

I am trying to use react-leaflet with preact with little success. I do actually render the map but it is not rendered together, as in the tiles are scattered over the page and outside the containing element.
I have read all (some) related questions on SO that say you need to either import the css file from leaflet (import "leaflet/dist/leaflet.css") or include a css file with a class for .leaflet-container. I have tried both and it is still not working.
I followed the instruction on the react leaflet website to install the necessary dependencies.
My project uses rollup so I added the following to my rollup config:
alias({
entries: [
{ find: 'react', replacement: 'preact/compat' },
{ find: 'react-dom', replacement: 'preact/compat' },
{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }
]
}),
And my component looks like this:
import { h } from 'preact';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import { Icon } from "leaflet";
import "../../styles/leaflet.css";
const Map = (): JSX.Element => {
type LatLngTuple = [number, number];
const position: LatLngTuple = [51.505, -0.09];
return (
<MapContainer center={position} zoom={13} scrollWheelZoom={false} >
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>
);
};
export default Map;

Related

Displaying TIFF data on React-Leaflet Map

I have basic javascript code that uses a simple Leaflet map; I have TIFF files that I parse through, and then I can display these on the map though Layer Control, in a simple index.html file. I can't figure out how to show the TIFF data in react-leaflet though. I can parse the data properly, but react-leaflet only seems to take PNG or PNG url's, and I can't find any documentation or anything that shows how to show TIFF files. I'm sure I'm missing something simple, but it's super frustrating :(
This is my code with react, and react-leaflet. It's working + parsing the TIFF data, I just don't know how to add the data to the layerscontrol baselayer TileLayer...
import React, { useMemo, useState } from "react";
import {
TileLayer,
Marker,
Popup,
MapContainer,
LayersControl,
LayerGroup,
FeatureGroup,
Circle,
useMap,
} from 'react-leaflet';
import chroma from 'chroma-js';
import parseGeoraster from 'georaster';
import GeoRasterLayer from 'georaster-layer-for-leaflet';
import AddLocate from "../components/AddLocate";
import { Helmet } from 'react-helmet';
import sample from '../data/tmin.tiff';
const MapBody = () => {
const center = [0, 0];
let tmin_layer = '';
fetch(sample)
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
parseGeoraster(arrayBuffer).then(georaster => {
const min = georaster.mins[0];
const max = georaster.maxs[0];
const range = georaster.ranges[0];
const scale = chroma.scale('Spectral').domain([1, 0]);
tmin_layer = new GeoRasterLayer({
georaster: georaster,
opacity: 0.7,
pixelValuesToColorFn: function (pixelValues) {
var pixelValue = pixelValues[0];
if (pixelValue === 0) return null;
const scaledPixelValue = (pixelValue - min) / range;
const color = scale(scaledPixelValue).hex();
return color;
},
resolution: 256
});
console.log("layer:", tmin_layer);
})
})
return (
<>
<Helmet>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
/>
</Helmet>
<MapContainer className="map" center={center} zoom={2} scrollWheelZoom={false} doubleClickZoom={true}>
<TileLayer
className="tile"
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
//prevents map duplicating
noWrap={true} />
<LayersControl position="topright">
<LayersControl.BaseLayer name="TOPO TESTING">
<TileLayer className="tiles" url="https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png"/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name="TIFF TEST">
<TileLayer className="tiffy" url={tmin_layer}/>
</LayersControl.BaseLayer>
</LayersControl>
<AddLocate/>
</MapContainer>
</>
)
}
export default MapBody;

react-mapbox-gl markers are not displayed correctly

I have a site with mapbox, the map itself works fine, but I can't add markers to it.
I copied the code from one source on which everything works, but when I added it to my project, the markers shifted from the correct coordinates on the map and got even more shifted when approaching.
here's my code
import React, { useState } from "react";
import ReactDOM from "react-dom";
import ReactMapboxGl, { Layer, Marker } from "react-mapbox-gl";
import { observer } from "mobx-react-lite";
import state from "../../state/state";
const Map = ReactMapboxGl({
accessToken:
"pk.eyJ1IjoibmFnaHQiLCJhIjoiY2wyYTJrazZxMDFlbzNpbnp0eTNnOG44aCJ9.i3nyiAJBTDyWviIWhsX-Zg",
});
const IndexMap = observer(({ coordinats }) => {
return (
<div style={{ height: "100vh", width: "100%", overflow: "hidden" }}>
<Map
style="mapbox://styles/mapbox/streets-v9" // eslint-disable-line
containerStyle={{
height: "100%",
width: "100%",
}}
center={{
lat: 51.5285582,
lng: -0.2416815,
}}
zoom={[12]}
>
<Marker coordinates={[-0.2416815, 51.5285582]} anchor="bottom">
<h1>marker</h1>
</Marker>
</Map>
</div>
);
});
export default IndexMap;
I think there are not enough styles for the map to set them in the right location.
I don't know what the problem was. I just moved the project to the folder with the working file. The link to the folder with the working file -https://codesandbox.io/embed/pwly8?codemirror=1

Problem whit sending my local position Leaflet

When I'm initializing the const it's like that
-lat and leg are available only inside the function and when I'm send them to the map (I'm usinge Leaflet) it doesn't show them and it gave me that error:
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
import {Component,useState,useEffect,useRef, ReactNode, CSSProperties, Link} from 'react';
import { MapContainer, TileLayer, Marker, Popup,useLeaflet,leafletElement} from 'react-leaflet'
function HomePage(){
const [lat, setLat] = useState(null);
const [lng, setLng] = useState(null);
const [status, setStatus] = useState(null);
if (!navigator.geolocation) {
setStatus('Geolocation is not supported by your browser');
} else {
setStatus('Locating...');
navigator.geolocation.getCurrentPosition((position) => {
setStatus(null);
setLat(position.coords.latitude);
setLng(position.coords.longitude);
console.log(lat,lng)
}, () => {
setStatus('Unable to retrieve your location');
});
}
const position = [lat,lng]
return(
<MapContainer center={position} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>
)};
export default HomePage
Your component is re-rendering constantly. I'm not sure but I think below should work. You have to use useEffect hook and add a check on navigator at the start of component if(!navigator.geolocation) { return null; }

react-google-maps StandaloneSearchBox set specific country restriction?

I am trying to set a specific country restriction using react-google-maps StandaloneSearchBox.
I have tried componentRestrictions, but I'm not sure how to use it.
Sharing my code below:
export const AutoCompleteSearchBox = compose(
withProps({
googleMapURL:googleMapUrl,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px`, top:'3px' }} />,
}),
lifecycle({
componentWillMount() {
const refs = {}
this.setState({
types: ['(regions)'],
componentRestrictions: {country: "bd"},
onSearchBoxMounted:ref =>{ refs.searchBox = ref; },
onPlacesChanged:()=>{
const places = refs.searchBox.getPlaces();
this.props.onPlacesChanged(places);
},
})
const options = {
types: ['(regions)'],
componentRestrictions:{ country: 'bd' }
}
},
}),
withScriptjs
)`(props =>
<div data-standalone-searchbox="">
<StandaloneSearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
onPlacesChanged={props.onPlacesChanged}
controlPosition={ window.google.maps.ControlPosition.TOP_LEFT}
>
<TextField
className={props.inputClass}
placeholder={props.inputPlaceholder}
label={props.inputLabel}
name={props.inputName}
value={props.inputValue}
onChange={props.inputOnChange}
helperText={props.inputHelperText}
error={props.inputError}
/>
</StandaloneSearchBox>
</div>
);`
How can I solve this problem?
You can't add such restrictions for the SearchBox results, but you can specify the area towards which to bias query predictions. Predictions are biased towards, but not restricted to, queries targeting these bounds.
If you want to show only specific places, then you can Google Place Autocomplete feature. For it you don't event need to use additional React libraries for Google Maps. Here's the example:
import React, { Component } from 'react';
import Script from 'react-load-script'
class LocationMap extends Component {
handleScriptLoad() {
const inputEl = document.getElementById('address-input');
/*global google*/
var options = {
//types: ['address'],
componentRestrictions: {country: 'by'}
};
this.autocomplete = new google.maps.places.Autocomplete(inputEl, options);
this.autocomplete.addListener('place_changed', this.handlePlaceSelect.bind(this));
}
handlePlaceSelect() {
console.log(this.autocomplete.getPlace());
}
render() {
return (
<section>
<Script
url="https://maps.googleapis.com/maps/api/js?key=API_KEY&v=3.33&libraries=places&language=en&region=US"
onLoad={this.handleScriptLoad.bind(this)}
/>
<div className="form-group">
<label htmlFor="address-map">Enter address</label>
<input type="text"
autoComplete="new-password"
className="form-control"
id="address-input"
name="address"/>
</div>
</section>
);
}
}
export default LocationMap;
Don't forget to add react-load-script package: npm i react-load-script --save

Material UI RTL

The RTL demo provided in material ui guides seems does not work for components.
As they said in the Right-to-left guide internally they are dynamically enabling jss-rtl plugin when direction: 'rtl' is set on the theme but in the demo only the html input is rtl and TextField isn't.
Here's the demo code from https://material-ui-next.com/guides/right-to-left/#demo
import React from 'react';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import TextField from 'material-ui/TextField';
const theme = createMuiTheme({
direction: 'rtl', // Both here and <body dir="rtl">
});
function Direction() {
return (
<MuiThemeProvider theme={theme}>
<div dir="rtl">
<TextField label="Name" />
<input type="text" placeholder="Name" />
</div>
</MuiThemeProvider>
);
}
export default Direction;
Once you have created a new JSS instance with the plugin, you need to
make it available to all components in the component tree. JSS has a
JssProvider component for this:
import { create } from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import { createGenerateClassName, jssPreset } from '#material-ui/core/styles';
// Configure JSS
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
// Custom Material-UI class name generator.
const generateClassName = createGenerateClassName();
function RTL(props) {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
{props.children}
</JssProvider>
);
}