Изменение позиции камеры

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 {LOCATION} from './common';

      window.map = null;

      main();
      async function main() {
        // Waiting for all api elements to be loaded
        await ymaps3.ready;
        const {YMap, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControlButton} = ymaps3;
        // Initialize the map
        map = new YMap(
          // Pass the link to the HTMLElement of the container
          document.getElementById('app'),
          // Pass the map initialization parameters
          {location: LOCATION, showScaleInCopyrights: true, camera: {tilt: (40 * Math.PI) / 180}},
          // Add a map scheme layer
          [new YMapDefaultSchemeLayer({})]
        );

        let hasAutoRotate = true;
        let frame = 0;

        function onActionStartHandler() {
          // Turn off the auto-rotation of the map flag at any event
          hasAutoRotate = false;
          autoRotateBtn.update({background: '#007afce6'});
        }
        // Creating a listener object
        const mapListener = new YMapListener({
          layer: 'any',
          // Adding an onActionStart handler to the listener
          onActionStart: onActionStartHandler
        });
        map.addChild(mapListener);

        // Add a shared container for YMapControlButton's and add it to the map
        const controls = new YMapControls({position: 'bottom'});
        map.addChild(controls);

        // Automatically rotate the camera
        function startAutoRotationCamera() {
          if (hasAutoRotate) {
            //  Divide degrees by 100 to slow rotation to ~10 degrees / sec
            map.update({camera: {azimuth: map.azimuth + (10 * Math.PI) / 180 / 120}});
            // Request the next frame of the animation
            frame = requestAnimationFrame(startAutoRotationCamera);
          } else {
            // If the automatic rotation mode is stopped then cancel the request for the next animation frame
            cancelAnimationFrame(frame);
          }
        }
        startAutoRotationCamera();

        // Add YMapControlButton's that will change the camera position when clicked
        function autoRotateBtnHandler() {
          hasAutoRotate = !hasAutoRotate;
          autoRotateBtn.update({background: hasAutoRotate ? '#fd6466e6' : '#007afce6'});
          startAutoRotationCamera();
        }
        const autoRotateBtn = new YMapControlButton({
          text: 'Auto Rotate',
          color: '#fff',
          background: '#fd6466e6',
          onClick: autoRotateBtnHandler
        });
        controls.addChild(autoRotateBtn);

        function rotateLeftBtnHandler() {
          onActionStartHandler();
          // Rotate the camera 30 degrees to the left (degrees need to be converted to radians)
          map.update({camera: {azimuth: map.azimuth - (30 * Math.PI) / 180, duration: 250}});
        }
        const rotateLeftBtn = new YMapControlButton({
          text: 'Rotate Left',
          color: '#fff',
          background: '#007afce6',
          onClick: rotateLeftBtnHandler
        });
        controls.addChild(rotateLeftBtn);

        function rotateRightBtnHandler() {
          onActionStartHandler();
          // Rotate the camera 30 degrees to the right (degrees need to be converted to radians)
          map.update({camera: {azimuth: map.azimuth + (30 * Math.PI) / 180, duration: 250}});
        }
        const rotateRightBtn = new YMapControlButton({
          text: 'Rotate Right',
          color: '#fff',
          background: '#007afce6',
          onClick: rotateRightBtnHandler
        });
        controls.addChild(rotateRightBtn);

        function upTiltBtnHandler() {
          onActionStartHandler();
          // Tilt the camera up 10 degrees (degrees need to be converted to radians)
          map.update({camera: {tilt: map.tilt - (10 * Math.PI) / 180, duration: 250}});
        }
        const upTiltBtn = new YMapControlButton({
          text: 'Up Tilt',
          color: '#fff',
          background: '#007afce6',
          onClick: upTiltBtnHandler
        });
        controls.addChild(upTiltBtn);

        function downTiltBtnHandler() {
          onActionStartHandler();
          // Tilt the camera down 10 degrees (degrees need to be converted to radians)
          map.update({camera: {tilt: map.tilt + (10 * Math.PI) / 180, duration: 250}});
        }
        const downTiltBtn = new YMapControlButton({
          text: 'Down tilt',
          color: '#fff',
          background: '#007afce6',
          onClick: downTiltBtnHandler
        });
        controls.addChild(downTiltBtn);
      }
    </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 {LOCATION} 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, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControlButton} = reactify.module(ymaps3);
        const {useState, useEffect, useRef, useCallback} = React;

        function App() {
          const [hasAutoRotate, setAutoRotate] = useState(true);
          const [mapAzimuth, setMapAzimuth] = useState(0);
          const [mapTilt, setMapTilt] = useState((40 * Math.PI) / 180);
          const frame = useRef < number > null;

          // Automatically rotate the camera
          const startAutoRotationCamera = useCallback(() => {
            if (hasAutoRotate) {
              //  Divide degrees by 100 to slow rotation to ~20 degrees / sec
              setMapAzimuth(map.azimuth + (10 * Math.PI) / 180 / 100);
              // Request the next frame of the animation
              frame.current = requestAnimationFrame(startAutoRotationCamera);
            } else {
              // If the automatic rotation mode is stopped then cancel the request for the next animation frame
              cancelAnimationFrame(frame.current);
            }
          }, [hasAutoRotate]);

          useEffect(() => {
            // Update ref to new animation frame ID
            frame.current = requestAnimationFrame(startAutoRotationCamera);

            // Kill animation cycle on component unmount
            return () => cancelAnimationFrame(frame.current);
          }, [startAutoRotationCamera]);

          const onActionStartHandler = useCallback(() => {
            // Turn off the auto-rotation of the map flag at any event
            setAutoRotate(false);
          }, []);

          const autoRotateBtnHandler = useCallback(() => {
            setAutoRotate((prevAutoRotate) => !prevAutoRotate);
          }, []);

          const rotateLeftBtnHandler = useCallback(() => {
            onActionStartHandler();
            // Rotate the camera 30 degrees to the left (degrees need to be converted to radians)
            setMapAzimuth(map.azimuth - (30 * Math.PI) / 180);
          }, []);

          const rotateRightBtnHandler = useCallback(() => {
            onActionStartHandler();
            // Rotate the camera 30 degrees to the right (degrees need to be converted to radians)
            setMapAzimuth(map.azimuth + (30 * Math.PI) / 180);
          }, []);

          const tiltUpBtnHandler = useCallback(() => {
            onActionStartHandler();
            // Tilt the camera up 10 degrees (degrees need to be converted to radians)
            setMapTilt(map.tilt - (10 * Math.PI) / 180);
          }, []);

          const tiltDownBtnHandler = useCallback(() => {
            onActionStartHandler();
            // Tilt the camera down 10 degrees (degrees need to be converted to radians)
            setMapTilt(map.tilt + (10 * Math.PI) / 180);
          }, []);

          return (
            // Initialize the map and pass initialization parameters
            <YMap
              location={LOCATION}
              showScaleInCopyrights={true}
              camera={{azimuth: mapAzimuth, tilt: mapTilt, duration: hasAutoRotate ? 0 : 250}}
              ref={(x) => (map = x)}
            >
              {/* Add a map scheme layer */}
              <YMapDefaultSchemeLayer />

              {/* Creating a listener component and adding an onActionStart handler to it */}
              <YMapListener onActionStart={onActionStartHandler} />

              {/* Add a shared container for YMapControlButton's */}
              <YMapControls position="bottom">
                {/* Add YMapControlButton's that will change the camera position when clicked */}
                <YMapControlButton
                  text="Auto Rotate"
                  color="#fff"
                  background={hasAutoRotate ? '#fd6466e6' : '#007afce6'}
                  onClick={autoRotateBtnHandler}
                />
                <YMapControlButton
                  text="Rotate Left"
                  color="#fff"
                  background="#007afce6"
                  onClick={rotateLeftBtnHandler}
                />
                <YMapControlButton
                  text="Rotate Right"
                  color="#fff"
                  background="#007afce6"
                  onClick={rotateRightBtnHandler}
                />
                <YMapControlButton text="Tilt Up" color="#fff" background="#007afce6" onClick={tiltUpBtnHandler} />
                <YMapControlButton
                  text="Tilt Down"
                  color="#fff"
                  background="#007afce6"
                  onClick={tiltDownBtnHandler}
                />
              </YMapControls>
            </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 {LOCATION} 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, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControlButton} = vuefy.module(ymaps3);

        const app = Vue.createApp({
          setup() {
            const location = Vue.ref(LOCATION);
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            const hasAutoRotate = Vue.ref(true);
            const mapAzimuth = Vue.ref(0);
            const mapTilt = Vue.ref((40 * Math.PI) / 180);
            let frameId;

            const autoRotateCamera = () => {
              if (hasAutoRotate.value) {
                mapAzimuth.value += (10 * Math.PI) / 180 / 100;
                frameId = requestAnimationFrame(autoRotateCamera);
              }
            };

            Vue.onMounted(() => {
              frameId = requestAnimationFrame(autoRotateCamera);
            });

            Vue.onUnmounted(() => {
              cancelAnimationFrame(frameId);
            });

            const onActionStartHandler = () => {
              hasAutoRotate.value = false;
            };

            const autoRotateBtnHandler = () => {
              hasAutoRotate.value = !hasAutoRotate.value;
              frameId = requestAnimationFrame(autoRotateCamera);
            };

            const rotateLeftBtnHandler = () => {
              onActionStartHandler();
              mapAzimuth.value = map.azimuth - (30 * Math.PI) / 180;
            };

            const rotateRightBtnHandler = () => {
              onActionStartHandler();
              mapAzimuth.value = map.azimuth + (30 * Math.PI) / 180;
            };

            const tiltUpBtnHandler = () => {
              onActionStartHandler();
              mapTilt.value = map.tilt - (10 * Math.PI) / 180;
            };

            const tiltDownBtnHandler = () => {
              onActionStartHandler();
              mapTilt.value = map.tilt + (10 * Math.PI) / 180;
            };

            return {
              location,
              refMap,
              hasAutoRotate,
              mapAzimuth,
              mapTilt,
              onActionStartHandler,
              autoRotateBtnHandler,
              rotateLeftBtnHandler,
              rotateRightBtnHandler,
              tiltUpBtnHandler,
              tiltDownBtnHandler
            };
          },
          components: {
            YMap,
            YMapDefaultSchemeLayer,
            YMapListener,
            YMapControls,
            YMapControlButton
          },
          template: `
    <YMap
      :location="location"
      :camera="{ azimuth: mapAzimuth, tilt: mapTilt, duration: hasAutoRotate ? 0 : 250 }"
      :ref="refMap"
    >
      <YMapDefaultSchemeLayer />
      <YMapListener @action-start="onActionStartHandler" />

      <YMapControls position="bottom">
        <YMapControlButton
          text="Auto Rotate"
          color="#fff"
          :background="hasAutoRotate ? '#fd6466e6' : '#007afce6'"
          @click="autoRotateBtnHandler"
        />
        <YMapControlButton
          text="Rotate Left"
          color="#fff"
          background="#007afce6"
          @click="rotateLeftBtnHandler"
        />
        <YMapControlButton
          text="Rotate Right"
          color="#fff"
          background="#007afce6"
          @click="rotateRightBtnHandler"
        />
        <YMapControlButton
          text="Tilt Up"
          color="#fff"
          background="#007afce6"
          @click="tiltUpBtnHandler"
        />
        <YMapControlButton
          text="Tilt Down"
          color="#fff"
          background="#007afce6"
          @click="tiltDownBtnHandler"
        />
      </YMapControls>
    </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>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
import type {YMapLocationRequest} from '@yandex/ymaps3-types';

export const LOCATION: YMapLocationRequest = {
  center: [37.537, 55.749], // starting position [lng, lat]
  zoom: 17 // starting zoom
};