0

If I try to make screenshots with my custom tiles, I am getting CORS errors. If I use mapbox or openstreet map tiles, I don't have any issues. I don't get any errors if custom tiles are used in Leaflet map, they are fetching with http 200 status.

enter image description here

When I make a screenshot, it looks like this:

enter image description here

and I am getting CORS errors when screenshot is generating:

Access to image at 'https://customTilesPlaceholder.com/tiles/orthophoto_tiles/21/608480/1304017.png' from origin 'https://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This is how I add my custom tiles to the leaflet. The drone tileLayer doesn't appear in screenshots.

const openStreetMap = tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 26,
    maxNativeZoom: 18,
  })
  let satellite = {} as TileLayer
  if (import.meta.env.VITE_MAPBOX_ACCESS_TOKEN) {
    satellite = tileLayer(
      `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/{z}/{x}/{y}?access_token=${
        import.meta.env.VITE_MAPBOX_ACCESS_TOKEN
      }`,
      { maxZoom: 26, maxNativeZoom: 22 }
    )
  }
  const customerTag = selectedUser?.value ? selectedUser.value : userData?.customerTag
  let overlayMaps: Record<string, TileLayer> = {}
  if (tileDirectories?.directories && tileDirectories?.config) {
    const orderedDirectories = orderDirectories(tileDirectories.directories, tileDirectories.config)
    if (import.meta.env.VITE_CUSTOM_MAP_TILES_URL && customerTag) {
      overlayMaps = orderedDirectories.reduce((acc, curr) => {
        let layer = {} as Layer
        layer = tileLayer(`${import.meta.env.VITE_CUSTOM_MAP_TILES_URL}${customerTag}/${curr}/{z}/{x}/{y}.png`, {
          minZoom: 11,
          maxZoom: 26,
          maxNativeZoom: 21,
          opacity: 1.0,
          tms: true,
        })
        return {
          ...acc,
          [curr]: layer,
        }
      }, {})
    }
  }
  let drone = {} as TileLayer
  if (import.meta.env.VITE_CUSTOM_MAP_TILES_URL) {
    drone = tileLayer(`${import.meta.env.VITE_CUSTOM_MAP_TILES_URL}orthophoto_tiles/{z}/{x}/{y}.png`, {
      minZoom: 11,
      maxZoom: 26,
      maxNativeZoom: 21,
      opacity: 1.0,
      tms: true,
    })
  }
  const baseMaps = {
    OpenStreetMap: openStreetMap,
    Satellite: satellite,
  }
  overlayMaps = {
    Drone: drone,
    ...overlayMaps,
  }
  Object.values(baseMaps).forEach((layer) => {
    layer.addTo(context.map)
  })
  Object.values(overlayMaps).forEach((layer) => {
    layer.addTo(context.map)
  })
  control.layers(baseMaps, overlayMaps).addTo(context.map)

This is the way how I take screenshots:

import { simpleMapScreenshoter } from 'lealfet;

const mapScreenshoter = simpleMapScreenshoter({
        hidden: true,
        hideElementsWithSelectors: ['.leaflet-control-container'],
        cropImageByInnerWH: true,
      }).addTo(context.map)

      mapScreenshoter
        .takeScreen('image', {
          mimeType: 'image/jpeg',
        })
        .then((base64Img) => {
          if (base64Img) {
            saveAs(base64Img, 'screen.png')
            // onTakeScreenshot?.(base64Img as unknown as string)
          }
        })
        .catch((e) => {
          alert(e.toString())
        })

Do you have any idea why leaflet-simple-map-screenshoter is throwing CORS errors for fetching custom tiles?

I tried to use crossorigin option for tileLayer with empty string or true value, but with this settings my custom tiles are not loading at all.

This is cors settings in Node.js server that is hosting map tiles:

app.use(
  cors({
    origin: [/localhost:\d{4}$/, /domain\.placeholder\.ai$/, /domain\.placeholder\.ai$/],
    maxAge: 86400, // NOTICE: 1 day
    credentials: true,
  })
)
5
  • @TomazicM it is npm library leaflet-simple-map-screenshoter
    – Matt
    Commented Mar 24 at 9:44
  • Where are custom tiles served from? Local server, like localhost? Please edit your question with more info.
    – TomazicM
    Commented Mar 24 at 10:25
  • @TomazicM I just edited my question. I found out that while screenshot is generating, I am getting CORS errors. I don't understand why, because tiles in my Leaflet map are loading with http 200 status without any errors.
    – Matt
    Commented Mar 24 at 10:32
  • You are getting CORS errors because screen shooter plugin manipulates canvas where layer tiles are drawn. Obviously your server CORS settings do not allow that. When I tried it with local IIS server, I had no problems with CORS. Since I'm not familiar with that, can't help you any further.
    – TomazicM
    Commented Mar 24 at 10:52
  • Thank for checking! I just found the issue and solution. I needed to add add_header Access-Control-Allow-Origin *; in nginx for fetching custom tiles
    – Matt
    Commented Mar 24 at 10:57

1 Answer 1

1

I needed to add add_header Access-Control-Allow-Origin *; in nginx for custom tiles routes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.