Изменение поведений карты

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 type {BehaviorType} from '@yandex/ymaps3-types';
      import {LOCATION, AVAILABLE_BEHAVIORS, INITIALLY_ENABLED_BEHAVIORS} from './common';

      window.map = null;

      main();
      async function main() {
          // Waiting for all api elements to be loaded
          await ymaps3.ready;

          // Create a custom control class for map behavior management
          interface BehaviorControlProps {
              behaviorName: string;
              checked: boolean;
              tooltip: boolean;
              onChange: (event: Event) => void;
          }
          class BehaviorControl extends ymaps3.YMapComplexEntity<BehaviorControlProps> {
              private _element: HTMLDivElement;
              private _detachDom: () => void;

              // Method for create a DOM control element
              _createElement(props: BehaviorControlProps) {
                  const {behaviorName, checked, tooltip, onChange} = props;

                  // Create a root element
                  const behaviorControl = document.createElement('div');
                  behaviorControl.className = 'behaviorControl';

                  // Create a title element
                  const title = document.createElement('div');
                  title.className = 'behaviorControl__title';
                  title.textContent = behaviorName;
                  behaviorControl.appendChild(title);

                  // Create a tooltip element if necessary
                  if (tooltip) {
                      const tooltipElement = document.createElement('div');
                      tooltipElement.className = 'behaviorControl__tooltip';
                      tooltipElement.setAttribute(
                          'tooltip-text',
                          'To reproduce this behavior, hold down ctrl/command + left mouse button.'
                      );

                      const tooltipIcon = document.createElement('img');
                      tooltipIcon.src = '../tooltip-icon.svg';

                      tooltipElement.appendChild(tooltipIcon);
                      behaviorControl.appendChild(tooltipElement);
                  }

                  // Create a label element
                  const label = document.createElement('label');
                  label.className = 'behaviorControl__label';
                  label.htmlFor = behaviorName;

                  // Create an input element (checkbox)
                  const input = document.createElement('input');
                  input.type = 'checkbox';
                  input.id = behaviorName;
                  input.checked = checked;
                  input.addEventListener('change', onChange);

                  // Create a slider element
                  const slider = document.createElement('div');
                  slider.className = 'behaviorControl__slider';

                  // Add elements to the label
                  label.appendChild(input);
                  label.appendChild(slider);

                  // Add the label to the root element
                  behaviorControl.appendChild(label);

                  return behaviorControl;
              }

              // Method for attaching the control to the map
              _onAttach() {
                  this._element = this._createElement(this._props);
                  this._detachDom = ymaps3.useDomContext(this, this._element, this._element);
              }

              // Method for detaching control from the map
              _onDetach() {
                  this._detachDom();
                  this._detachDom = null;
                  this._element = null;
              }
          }

          // State with active map behaviors
          let behaviors = INITIALLY_ENABLED_BEHAVIORS;

          const {YMap, YMapDefaultSchemeLayer, YMapControls, YMapControl} = 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, behaviors: behaviors},
              // Add a map scheme layer
              [new YMapDefaultSchemeLayer({})]
          );

          // Using YMapControls you can change the position of the control
          const controls = new YMapControls({position: 'right top'});
          map.addChild(controls);

          // Create a shared container for custom BehaviorControl's and add it to the map
          const control = new YMapControl();
          controls.addChild(control);

          // Create a BehaviorControls to change the behavior of the map
          AVAILABLE_BEHAVIORS.forEach((behaviorName) => {
              control.addChild(
                  new BehaviorControl({
                      behaviorName,
                      checked: behaviors.includes(behaviorName),
                      tooltip: behaviorName === 'mouseRotate' || behaviorName === 'mouseTilt',
                      onChange: onChangeBehaviorHandler
                  })
              );
          });

          // Handler function for add or remove map behavior
          function onChangeBehaviorHandler(event: Event) {
              const target = event.target as HTMLInputElement;
              const behaviorName = target.id as BehaviorType;
              const checked = target.checked;

              if (checked) {
                  behaviors.push(behaviorName);
              } else {
                  behaviors = behaviors.filter((behavior) => behavior !== behaviorName);
              }
              map.setBehaviors(behaviors);
          }
      }
    </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 type {BehaviorType} from '@yandex/ymaps3-types';
      import {LOCATION, AVAILABLE_BEHAVIORS, INITIALLY_ENABLED_BEHAVIORS} 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, YMapControls, YMapControl} = reactify.module(ymaps3);
          const {useState, useCallback} = React;

          // Create a custom control component for map behavior management
          interface BehaviorControlProps {
              behaviorName: string;
              checked: boolean;
              tooltip: boolean;
              onChange: (event: React.FormEvent<HTMLLabelElement>) => void;
          }
          function BehaviorControl(props: BehaviorControlProps) {
              const {behaviorName, checked, tooltip, onChange} = props;

              return (
                  <div className="behaviorControl">
                      <div className="behaviorControl__title">{behaviorName}</div>
                      {tooltip && (
                          <div
                              className="behaviorControl__tooltip"
                              tooltip-text="To reproduce this behavior, hold down ctrl/command + left mouse button."
                          >
                              <img src="../tooltip-icon.svg" alt="tooltip-icon" />
                          </div>
                      )}
                      <label className="behaviorControl__label" htmlFor={behaviorName} onChange={onChange}>
                          <input type="checkbox" id={behaviorName} checked={checked} />
                          <div className="behaviorControl__slider"></div>
                      </label>
                  </div>
              );
          }

          function App() {
              // State with active map behaviors
              const [behaviors, setBehaviors] = useState<BehaviorType[]>(INITIALLY_ENABLED_BEHAVIORS);

              // Handler function for add or remove map behavior
              const onChangeBehaviorHandler = useCallback(
                  (event: React.FormEvent<HTMLLabelElement>) => {
                      const target = event.target as HTMLInputElement;
                      const behaviorName = target.id as BehaviorType;
                      const checked = target.checked;

                      if (checked) {
                          setBehaviors([...behaviors, behaviorName]);
                      } else {
                          setBehaviors(behaviors.filter((behavior) => behavior !== behaviorName));
                      }
                  },
                  [behaviors]
              );

              return (
                  // Initialize the map and pass initialization parameters
                  <YMap location={LOCATION} showScaleInCopyrights={true} behaviors={behaviors} ref={(x) => (map = x)}>
                      {/* Add a map scheme layer */}
                      <YMapDefaultSchemeLayer />

                      {/* Using YMapControls you can change the position of the control */}
                      <YMapControls position="top right">
                          {/* Add a shared container to the map for custom BehaviorControl's */}
                          <YMapControl>
                              {/* Add a BehaviorControls to the map to change the behavior of the map */}
                              {AVAILABLE_BEHAVIORS.map((behaviorName) => (
                                  <BehaviorControl
                                      key={behaviorName}
                                      behaviorName={behaviorName}
                                      checked={behaviors.includes(behaviorName)}
                                      tooltip={behaviorName === 'mouseRotate' || behaviorName === 'mouseTilt'}
                                      onChange={onChangeBehaviorHandler}
                                  />
                              ))}
                          </YMapControl>
                      </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 type {BehaviorType} from '@yandex/ymaps3-types';
      import {LOCATION, AVAILABLE_BEHAVIORS, INITIALLY_ENABLED_BEHAVIORS} 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, YMapControls, YMapControl} = vuefy.module(ymaps3);

        const BehaviorControl = Vue.defineComponent({
          props: {
            behaviorName: String,
            checked: Boolean,
            tooltip: Boolean
          },
          emits: ['changeBehavior'],
          template: `
        <div class="behaviorControl">
            <div class="behaviorControl__title">{{behaviorName}}</div>
            <div v-if="tooltip"
                class="behaviorControl__tooltip"
                tooltip-text="To reproduce this behavior, hold down ctrl/command + left mouse button."
            >
                <img src="../tooltip-icon.svg" alt="tooltip-icon" />
            </div>
            <label
            class="behaviorControl__label"
            :for="behaviorName"
            >
              <input type="checkbox" :id="behaviorName" :checked="checked" 
              @change="$emit('changeBehavior', $event.target.checked, behaviorName)"/>
              <div class="behaviorControl__slider"></div>
            </label>
        </div>
    `
        });

        const app = Vue.createApp({
          components: {
            YMap,
            YMapDefaultSchemeLayer,
            BehaviorControl,
            YMapControls,
            YMapControl
          },
          setup() {
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            const availableBehaviors = AVAILABLE_BEHAVIORS;
            const behaviors = Vue.ref([...INITIALLY_ENABLED_BEHAVIORS]);

            // Handler function for add or remove map behavior
            const onChangeBehaviorHandler = (event, behaviorName) => {
              const checked = event; //.target.checked;
              if (checked) {
                behaviors.value.push(behaviorName);
              } else {
                behaviors.value = behaviors.value.filter((b) => b !== behaviorName);
              }
              behaviors.value = [...behaviors.value];
            };

            return {
              LOCATION,
              refMap,
              availableBehaviors,
              behaviors,
              onChangeBehaviorHandler
            };
          },
          template: `
            <!--Initialize the map and pass initialization parameters-->
            <YMap :location="LOCATION" :showScaleInCopyrights="true" :behaviors="behaviors" :ref="refMap">
                <!--Add a map scheme layer-->
                <YMapDefaultSchemeLayer />

                <!-- Using YMapControls you can change the position of the control -->
                <YMapControls position="top right">
                    <!-- Add a shared container to the map for custom BehaviorControl's -->
                    <YMapControl>
                        <!-- Add a BehaviorControls to the map to change the behavior of the map -->
                        <BehaviorControl
                          v-for="behaviorName in availableBehaviors"
                          :key="behaviorName"
                          :behaviorName="behaviorName"
                          :checked="behaviors.includes(behaviorName)"
                          :tooltip="['mouseRotate', 'mouseTilt'].includes(behaviorName)"
                          @changeBehavior="onChangeBehaviorHandler"
                        />
                    </YMapControl>
                </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>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
.behaviorControl {
  padding: 5px;
  display: flex;
  align-items: center;
  gap: 7px;
}

.behaviorControl__title {
  font-size: 16px;
}

.behaviorControl__tooltip {
  position: relative;
  width: 20px;
  height: 20px;
}

.behaviorControl__tooltip img {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  object-fit: cover;
}

[tooltip-text] {
  position: relative;
  cursor: help;
}
[tooltip-text]::after {
  content: attr(tooltip-text);

  width: 250px;
  padding: 10px;

  position: absolute;
  left: -270px;

  background-color: rgba(255, 255, 255, 0.9);
  font-size: 16px;

  opacity: 0;
  pointer-events: none;

  transition: opacity 0.3s;
}
[tooltip-text]:hover::after {
  opacity: 1;
}

.behaviorControl__label {
  margin-left: auto;

  height: 22px;
  width: 40px;

  display: inline-block;
  position: relative;
}

.behaviorControl__label input {
  display: none;
}

.behaviorControl__slider {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  top: 0;

  cursor: pointer;
  border-radius: 22px;
  background-color: #ccc;
  transition: 0.4s;
}

.behaviorControl__slider:before {
  content: '';
  width: 16px;
  height: 16px;

  position: absolute;
  bottom: 3px;
  left: 3px;

  border-radius: 50%;
  background-color: #fff;
  transition: 0.4s;
}

.behaviorControl__label input:checked + .behaviorControl__slider {
  background-color: #007afce6;
}

.behaviorControl__label input:checked + .behaviorControl__slider:before {
  transform: translateX(18px);
}
import type {YMapLocationRequest, BehaviorType} from '@yandex/ymaps3-types';

export const LOCATION: YMapLocationRequest = {
  center: [37.623082, 55.75254], // starting position [lng, lat]
  zoom: 9 // starting zoom
};

// An array with initially enabled map behaviors
export const INITIALLY_ENABLED_BEHAVIORS: BehaviorType[] = ['drag', 'scrollZoom', 'dblClick'];

// An array of available map behaviors. These are just some of the behaviors, you can see them all in the documentation
export const AVAILABLE_BEHAVIORS: BehaviorType[] = ['drag', 'scrollZoom', 'dblClick', 'mouseRotate', 'mouseTilt'];