Создание собственной карты

Open on 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://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></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 {mapParameters, PIC_WIDTH, PIC_HEIGHT, worldSize, dataSourceProps, layerProps} from './common';

      window.map = null;

      main();
      async function main() {
        // Waiting for all api elements to be loaded
        await ymaps3.ready;
        const {YMap, YMapLayer, YMapTileDataSource, YMapDefaultFeaturesLayer} = ymaps3;
        const {Cartesian} = await ymaps3.import('@yandex/ymaps3-cartesian-projection@0.0.1');
        const {YMapDefaultMarker} = await ymaps3.import('@yandex/ymaps3-markers@0.0.1');

        // We set as a projection Cartesian. With this calculation, the center of the image will lie in the coordinates [0, 0].
        mapParameters.projection = new Cartesian([
          [-PIC_WIDTH / 2, PIC_HEIGHT / 2 - worldSize],
          [worldSize - PIC_WIDTH / 2, PIC_HEIGHT / 2]
        ]);
        map = new YMap(
          // Pass the link to the HTMLElement of the container
          document.getElementById('app'),
          // Pass the map initialization parameters with the cartesian projection
          mapParameters,
          [
            // Adding our own data source
            new YMapTileDataSource(dataSourceProps),
            // Adding a layer that will display data from `dataSource`
            new YMapLayer(layerProps),
            // Adding a geo object data source to add a marker to the map
            new YMapDefaultFeaturesLayer({}),
            // Adding a marker to the center of the map
            new YMapDefaultMarker({
              coordinates: [0, 0]
            })
          ]
        );
      }
    </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" />
  </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://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

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

      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 @yandex/ymaps3-reactify
        const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]);
        const reactify = ymaps3React.reactify.bindTo(React, ReactDOM);
        const {YMap, YMapLayer, YMapTileDataSource, YMapDefaultFeaturesLayer} = reactify.module(ymaps3);
        const {Cartesian} = await ymaps3.import('@yandex/ymaps3-cartesian-projection@0.0.1');
        const {YMapDefaultMarker} = reactify.module(await ymaps3.import('@yandex/ymaps3-markers@0.0.1'));

        // We set as a projection Cartesian. With this calculation, the center of the image will lie in the coordinates [0, 0].
        mapParameters.projection = new Cartesian([
          [-PIC_WIDTH / 2, PIC_HEIGHT / 2 - worldSize],
          [worldSize - PIC_WIDTH / 2, PIC_HEIGHT / 2]
        ]);

        function App() {
          return (
            // Initialize the map and pass initialization parameters with the cartesian projection
            <YMap {...mapParameters} ref={(x) => (map = x)}>
              {/* Adding our own data source */}
              <YMapTileDataSource {...dataSourceProps} />
              {/* Adding a layer that will display data from `dataSource`s */}
              <YMapLayer {...layerProps} />
              {/* Adding a geo object data source to add a marker to the map */}
              <YMapDefaultFeaturesLayer />
              {/* Adding a marker to the center of the map */}
              <YMapDefaultMarker coordinates={[0, 0]} />
            </YMap>
          );
        }

        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" />
  </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://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></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 {mapParameters, PIC_WIDTH, PIC_HEIGHT, worldSize, dataSourceProps, layerProps} from './common';

      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 @yandex/ymaps3-vuefy
        const [ymaps3Vue] = await Promise.all([ymaps3.import('@yandex/ymaps3-vuefy'), ymaps3.ready]);
        const vuefy = ymaps3Vue.vuefy.bindTo(Vue);
        const {YMap, YMapLayer, YMapTileDataSource, YMapDefaultFeaturesLayer} = vuefy.module(ymaps3);
        const {Cartesian} = await ymaps3.import('@yandex/ymaps3-cartesian-projection@0.0.1');
        const {YMapDefaultMarker} = vuefy.module(await ymaps3.import('@yandex/ymaps3-markers@0.0.1'));

        // We set as a projection Cartesian. With this calculation, the center of the image will lie in the coordinates [0, 0].
        mapParameters.projection = new Cartesian([
          [-PIC_WIDTH / 2, PIC_HEIGHT / 2 - worldSize],
          [worldSize - PIC_WIDTH / 2, PIC_HEIGHT / 2]
        ]);

        const app = Vue.createApp({
          components: {
            YMap,
            YMapLayer,
            YMapTileDataSource,
            YMapDefaultFeaturesLayer,
            YMapDefaultMarker
          },
          setup() {
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            return {
              refMap,
              dataSourceProps,
              layerProps,
              mapParameters
            };
          },
          template: `
          <!-- Initialize the map and pass initialization parameters -->
          <YMap v-bind="mapParameters" :ref="refMap">
            <!-- Adding our own data source -->
            <YMapTileDataSource v-bind="dataSourceProps"/>
            <!-- Adding a layer that will display data from dataSources -->
            <YMapLayer v-bind="layerProps"/>
            <!-- Adding a geo object data source to add a marker to the map -->
            <YMapDefaultFeaturesLayer/>
            <!-- Adding a marker to the center of the map -->
            <YMapDefaultMarker :coordinates="[0, 0]"/>
          </YMap>`
        });
        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" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
body {
  display: flex;
  justify-content: center;
  align-items: center;

  background: linear-gradient(180deg, #a5a5a5, #dcdcdc);
}

#app {
  width: 100%;
  height: 100%;

  max-width: 1200px;
  max-height: 600px;
}
import type {YMapTileDataSourceProps, YMapLayerProps, YMapProps, LngLatBounds} from '@yandex/ymaps3-types';

const TILES_PATH = 'https://yastatic.net/s3/front-maps-static/maps-front-jsapi-3/examples/images/custom-map/tiles';

/* To calculate the coordinates of the lower left and upper right corners of a rectangular coordinate
 * area, we need to know the maximum zoom, width and height of the image in pixels at maximum zoom.
 */
export const MAX_ZOOM = 4;
export const PIC_WIDTH = 2526;
export const PIC_HEIGHT = 1642;

export const dataSourceProps: YMapTileDataSourceProps = {
  id: 'custom',
  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: TILES_PATH + '/z/tile-x-y.jpg'
  },
  zoomRange: {min: 3, max: 4},
  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: YMapLayerProps = {
  id: 'customLayer',
  source: 'custom',
  type: 'ground',
  options: {
    raster: {
      awaitAllTilesOnFirstDisplay: true
    }
  }
};

// Calculate the size of all tiles at the maximum zoom.
export const worldSize = Math.pow(2, MAX_ZOOM) * 256;

// Limiting the scrolling area of our map to the size of the entire image
const RESTRICT_AREA: LngLatBounds = [
  [-PIC_WIDTH / 2, -PIC_HEIGHT / 2],
  [PIC_WIDTH / 2, PIC_HEIGHT / 2]
];

export const mapParameters: YMapProps = {
  location: {center: [0, 0], zoom: 3},
  projection: null,
  mode: 'raster',
  restrictMapArea: RESTRICT_AREA,
  // Do not copy the world along the axes
  worldOptions: {cycledX: false, cycledY: false}
};