Custom map type

Open in CodeSandbox

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {dataSourceProps, layerProps} from './common';
      import {LOCATION} from '../variables';

      window.map = null;

      main();
      async function main() {
        // Waiting for all api elements to be loaded
        await mappable.ready;
        const {SphericalMercator} = await mappable.import(
          '@mappable-world/mappable-spherical-mercator-projection@0.0.1'
        );
        const {MMap, MMapDefaultSchemeLayer, MMapTileDataSource, MMapLayer} = mappable;
        // Initialize the map
        map = new MMap(
          // Pass the link to the HTMLElement of the container
          document.getElementById('app'),
          // Pass the map initialization location and the Mercator projection used to represent the Earth's surface on a plane
          {location: LOCATION, showScaleInCopyrights: true, projection: new SphericalMercator()},
          [
            // Adding our own data source
            new MMapTileDataSource(dataSourceProps),
            // Adding a layer that will display data from `dataSource`
            new MMapLayer(layerProps),
            // Add a map scheme layer
            new MMapDefaultSchemeLayer({})
          ]
        );
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
    <link rel="stylesheet" href="../variables.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
      import {dataSourceProps, layerProps} from './common';
      import {LOCATION} from '../variables';

      window.map = null;

      main();
      async function main() {
        // For each object in the JS API, there is a React counterpart
        // To use the React version of the API, include the module @mappable-world/mappable-reactify
        const [mappableReact] = await Promise.all([
          mappable.import('@mappable-world/mappable-reactify'),
          mappable.ready
        ]);
        const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
        const {SphericalMercator} = await mappable.import(
          '@mappable-world/mappable-spherical-mercator-projection@0.0.1'
        );
        const {MMap, MMapDefaultSchemeLayer, MMapLayer, MMapTileDataSource} = reactify.module(mappable);

        function App() {
          return (
            // Initialize the map and pass initialization location and the Mercator projection used to represent the Earth's surface on a plane
            <MMap
              location={LOCATION}
              showScaleInCopyrights={true}
              projection={new SphericalMercator()}
              ref={(x) => (map = x)}
            >
              <MMapDefaultSchemeLayer />
              {/* Adding our own data source */}
              <MMapTileDataSource {...dataSourceProps} />
              {/* Adding a layer that will display data from `dataSource`s */}
              <MMapLayer {...layerProps} />
            </MMap>
          );
        }

        ReactDOM.render(
          <React.StrictMode>
            <App />
          </React.StrictMode>,
          document.getElementById('app')
        );
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
    <link rel="stylesheet" href="../variables.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {dataSourceProps, layerProps} from './common';
      import {LOCATION} from '../variables';

      window.map = null;

      async function main() {
        // For each object in the JS API, there is a Vue counterpart
        // To use the Vue version of the API, include the module @mappable-world/mappable-vuefy
        const [mappableVue] = await Promise.all([mappable.import('@mappable-world/mappable-vuefy'), mappable.ready]);
        const vuefy = mappableVue.vuefy.bindTo(Vue);
        const {SphericalMercator} = await mappable.import(
          '@mappable-world/mappable-spherical-mercator-projection@0.0.1'
        );
        const {MMap, MMapDefaultSchemeLayer, MMapLayer, MMapTileDataSource} = vuefy.module(mappable);

        const app = Vue.createApp({
          components: {MMap, MMapLayer, MMapTileDataSource, MMapDefaultSchemeLayer},
          setup() {
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            const projection = new SphericalMercator();
            return {LOCATION, refMap, projection, dataSourceProps, layerProps};
          },
          template: `
            <!--Initialize the map and pass initialization location and the Mercator projection used to represent the Earth's surface on a plane-->
            <MMap :location="LOCATION" :projection="projection" :showScaleInCopyrights="true" :ref="refMap">
                <MMapDefaultSchemeLayer />
                <!--Adding our own data source-->
                <MMapTileDataSource v-bind="dataSourceProps" />
                <!--Adding a layer that will display data from \`dataSource\`s-->
                <MMapLayer v-bind="layerProps" />
            </MMap>`
        });
        app.mount('#app');
      }
      main();
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
    <link rel="stylesheet" href="../variables.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
import type {MMapTileDataSourceProps, MMapLayerProps} from '@mappable-world/mappable-types';

export const dataSourceProps: MMapTileDataSourceProps = {
  id: 'custom',
  copyrights: ['© OpenRailwayMap contributors'],
  raster: {
    type: 'ground',

    /*
        fetchTile is called to get data for displaying a custom tile
        This method can be of several variants:
        1) x y z placeholders for tile coordinates
        2) method that returns final url
        3) method that fetches tile manually

        In this example, we use option 1
        */
    fetchTile: 'https://tiles.openrailwaymap.org/standard/{{z}}/x/y.png'
  },
  zoomRange: {min: 0, max: 19},
  clampMapZoom: true
};
/*
    A text identifier is used to link the data source and the layer.
    Be careful, the identifier for the data source is set in the id field,
    and the source field is used when transferring to the layer
*/
export const layerProps: MMapLayerProps = {
  id: 'customLayer',
  source: 'custom',
  type: 'ground',
  options: {
    raster: {
      awaitAllTilesOnFirstDisplay: true
    }
  }
};
import type {MMapLocationRequest} from '@mappable-world/mappable-types';

export const LOCATION: MMapLocationRequest = {
  center: [55.3226, 24.9671], // starting position [lng, lat]
  zoom: 8.2 // starting zoom
};