When I run my local .png tile library in a simple Leaflet index.html I get perfectly rendered and geo-correct tiles:
<script>
function onLoad() {
var mymap = L.map('mapid').setView([-42.132, 147.175], 12);
L.tileLayer('demo-map/{z}/{x}/{y}.png',
{ maxZoom: 16 }).addTo(mymap);
}
</script>
</head>
<body onload="onLoad();">
<div id="mapid" style="height: 500px;"></div>
</body>
But when I put the same path in "url=" in react-leaflet TileLayer, the tiles do not render.
<BaseLayer checked name="Local Map (Offline)">
<TileLayer
attribution="This map is offline"
url="demo-map/{z}/{x}/{y}.png"
/>
</BaseLayer>
The .png tiles are stored in src/demo-map/ in the same directory structure that Mobile Atlas Creator exported
Can anyone help me load my tiles in react-leaflet, or suggest a method incorporating standard Leaflet into my React app, bypassing react-leaflet and TileLayer?
Thank you
what worked for me, is that i moved my tiles folder into the public directory, then in the jsx code I refer to it like this :
and this is my directory :
Related
I am instantiating a leaflet map, but the tiles are basically being scattered all over the page - while the map is within a div, most of the tiles are not respecting that boundary:
<div class="widget-content listing-search-map-widget-content">
<div class="ih-map"
id="Map_5333811_16"
style="height:450px;"
data-centerpoint="38.573955 -121.442478"
data-mousewheel="true"
data-maptype="TERRAIN"
data-zoom="8"
>
</div>
</div>
The javascript comes down to:
mapOptions = {
attributionControl: true,
center: {
lat: 38.573955
lng: -121.442478
},
centerpoint: "38.573955,-121.442478",
layers: {},
maptype: "Terrain",
scrollWheelZoom: false,
zoom: 8
}
var map = L.map( "Map_5333811_16", mapOptions );
What would cause the tiles to plot all over the place?a couple of tiles are within the bounds of the div, but not the rest of them. You can see a screenshot of what happens here:
This sounds like a symptom of missing Leaflet CSS file, or incorrect version of that file.
As has been pointed out, this is solved by importing the CSS files.
Classically, you include the link to your CSS stylesheet in the head section of your document:
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
Or, in my case, stumbling across this problem while adapting Vue CLI's Webpack template, by adding
import "leaflet/dist/leaflet.css";
into the main.js file.
The key lines of CSS appear to be these:
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
so knowing that you can insert them at whatever point in your project suits your style.
add these to your index.html
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
I have a GatsbyJS site that I am working on where the main content source is a Wordpress install. One of the things I like to add to my sites is the ability to have placeholder areas in the site where I can control the content via the CMS. Usually I have a header_scripts area that goes at the bottom of the <head> tag, a body_scripts area that goes at the start of the <body> tag, and a footer_scripts area that goes at the bottom of the page <body>. With these three, I can usually integrate third-party add-ins pretty easily without having to do code deployments.
Sometimes I need to embed stylesheets, sometimes I need to embed script tags, and sometimes I need to throw in <meta> tags. Really the content could be anything. This data comes back as a raw string from my Wordpress GraphQL endpoint.
So now my question is, how do I get this content injected into my Gatsby site in the following places:
<html>
<head>
...
{header_scripts}
</head>
<body>
{body_scripts}
...
{footer_scripts}
</body>
</html>
I've found so far that I can just include the body_scripts and footer_scripts in a fairly regular manner in my Gatsby page template. In gatsby-node.js, I pass in the property values using the pageContext. It's kind of a bummer that they need to be wrapped in a <div /> tag, but they seem to work just fine.
import React from 'react'
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
Now for the real question. I am stumped on how to get the dynamic content from the header_scripts into the Gatsby server-side-rendering <head> tag. The closest thing I have found to being able to inject content into the head is to leverage the gatsby-ssr.js onRenderBody function. However, this seems to require pre-determined React component instances in order to function. I can't just pass it in plain raw string content and see the output in the page source:
export const onRenderBody = async ({
pathname,
setHeadComponents,
setHtmlAttributes,
setBodyAttributes,
setPreBodyComponents,
setPostBodyComponents,
setBodyProps
}, pluginOptions) => {
setHeadComponents(['<script>alert("hello");</script>'])
}
This results in an escaped string getting inserted into the <head> tag:
<html>
<head>
...
<script>alert("hello");</script>
</head>
<body>
...
</body>
</html>
I'm at a loss as to how to proceed. I can't just wrap my string in a <div /> tag like in the body because div tags can't go inside the head tag. I can't think of any head-capable HTML tags that would accept this kind of content.
The only idea I've had is to actually parse the string content into full React components. This seems daunting given the number of possible tags & formatting that I would need to support.
Am I going about this the wrong way? How can I get my arbitrary content into my Gatsby site's head tag?
It's a broad question and it will need some trials and errors to ensure that it's fully working without caveats in all scenarios but, among the things you've tried, you can add a few more options to the list to check which ones fit better.
Regarding the body_scripts and footer_scripts both can be inserted using the:
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
In any desired page or template. For the header_scripts and the meta tags (SEO), you can use the <Helmet> component. Basically, using this component, everything that is wrapped inside, it's becomes transpiled inside the <head> tag once compiled.
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
<Helmet>
{this.props.pageContext.headerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.headScripts}} />
)}
</Helmet>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
However, if the data comes from a CMS, it won't be available in the SSR yet, so, one easy thing you can do is to customize the outputted HTML (html.js) that Gatsby generates in each compilation. From the docs:
Customizing html.js is a workaround solution for when the use of the
appropriate APIs is not available in gatsby-ssr.js. Consider using
onRenderBody or onPreRenderHTML instead of the method above. As a
further consideration, customizing html.js is not supported within a
Gatsby Theme. Use the API methods mentioned instead.
Run:
cp .cache/default-html.js src/html.js
Or manually, copy the .cache/default-html.js file and paste it /src folder. There you can customize the final HTML.
Just wondering what the procedure is loading an external script into a component which renders HTML?
I call a script, which returns me an unordered list which i want to use for an image carousel it looks something like this but currently isn't working
this is what i have inside my render
return(
<Slick {...settings}>
<script
type="text/javascript"
src="https://some.external.script.js"
/>
<div
class="render-html-here-from-script"
/>
<script>
SomeScript.require(['xxx'], function(arg)
{arg.loadAll().done(function(embed) {
// code here gets list and binds above in div
})}
)
</script>
</Slick>
)
the above code works fine if I just copy/paste straight into a standard HTML page
Thanks
I'm currently in the process of learning React, so I've build my little game based on react components and I wanted to add translations for the various buttons needed.
The way we usually approach this is that the texts and translations are handled and edited by the client (as in the people we work for) on the server. Those translations would then be rendered right into the html template so that was it.
In React, however, everything is in js and component based. Does this mean that to make the move towards react we have to change our whole localization system, even on the server? Am I doing something wrong?
I tried having this
<script>
var translations = {
start: "Spiel starten"
}
</script>
<div id="App"></div> <!-- this is where I render React -->
but it looks like translations is undefined in my React App.js file
One option for handling this situation could be perhaps to pass in your translations object as a property on your component. For example:
<script>
var translations = {
start: "Spiel starten"
}
</script>
<div id="App"></div>
ReactDOM.render(
<Game translations={translations} />,
document.getElementById('App'));
As you have passed in your translations object into your react component, you should be able to use it in your template as such:
var Game = React.createClass({
render: function(){
return (
<div>
{this.props.translations.start}
</div>
);
}
});
I am a newbie to leaflet.js. Can anyone help me with debugging the following code? I am trying to show a map on screen but only zoom-in and zoom-out button shows up on Google Chrome and the map screen is empty.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<style>
#mapid { height: 180px; }
</style>
</head>
<body>
<div id="mapid"></div>
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script>
var mymap = L.map('mapid').setView([51.505, -0.09], 13);
</script>
</body>
</html>
Here is your corrected code: http://plnkr.co/edit/E7dw2AuNbLneYpz51Qdi?p=preview
There is no tile provider in your code, so nothing is showing in your map.
Check out the source of http://leafletjs.com/examples/quick-start-example.html
var mymap = L.map('mapid').setView([51.505, -0.09], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
If you don't want tiles from mapbox, you can use openstreet map
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(mymap);
Re-read the Leaflet quick-start tutorial, in particular this bit:
It’s worth noting that Leaflet is provider-agnostic, meaning that it doesn’t enforce a particular choice of providers for tiles, and it doesn’t even contain a single provider-specific line of code.
Leaflet doesn't add any default map data. It's up to you to tell Leaflet which data (vector features, tile layers) you want to show.
In case anyone else like me comes here looking for answers to why Leaflet isn't displaying, I found that Chrome would not display my map unless I set the width of the div, as well as the height.
As has been previously said, that wasn't the primary issue in the OP's case, but their code is also missing a width specification.