Элементы управления
html
<yandex-map
v-model="map"
:height="isFullscreen ? '100dvh' : height"
:settings="{
location: {
center,
zoom,
},
theme,
showScaleInCopyrights: true,
}"
:width="width"
>
<yandex-map-default-scheme-layer/>
<yandex-map-default-features-layer/>
<yandex-map-controls :settings="{ position: 'right' }">
<yandex-map-zoom-control/>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'bottom' }">
<yandex-map-zoom-control/>
<yandex-map-scale-control/>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'top' }">
<yandex-map-control-button :settings="{ onClick: shiftRight }">
<
</yandex-map-control-button>
<component
:is="component.component"
v-for="(component, index) in buttons.slice(0, 4)"
:key="index"
:settings="'props' in component ? component.props : {}"
>
{{ isRef(component.content) ? component.content.value : component.content }}
</component>
<yandex-map-control-button :settings="{ onClick: shiftLeft }">
>
</yandex-map-control-button>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'bottom left', orientation: 'vertical' }">
<yandex-map-open-maps-button/>
<yandex-map-open-maps-button :settings="{ title: 'Кастомный заголовок!' }"/>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'left' }">
<yandex-map-geolocation-control/>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'top left' }">
<yandex-map-entity>
<div
class="counter"
:data-value="counter"
@click="updateCounter"
>
Entity counter #{{ counter }}
</div>
</yandex-map-entity>
</yandex-map-controls>
<yandex-map-controls :settings="{ position: 'top right', orientation: 'vertical' }">
<yandex-map-control-button :settings="{ onClick: toggleFullscreen }">
<div
class="fullscreen"
:class="{ 'exit-fullscreen': isFullscreen }"
/>
</yandex-map-control-button>
<yandex-map-control-button>
<div class="button-element">
Button with element
</div>
</yandex-map-control-button>
<yandex-map-control>
<div class="button-element">
Control with element
#{{ counter }}
</div>
</yandex-map-control>
<yandex-map-control :settings="{ transparent: true }">
<div class="button-element">
Control without bg/shadow
</div>
</yandex-map-control>
</yandex-map-controls>
</yandex-map>
ts
import {
YandexMap,
YandexMapControl,
YandexMapControlButton,
YandexMapControls,
YandexMapDefaultFeaturesLayer,
YandexMapDefaultSchemeLayer,
YandexMapEntity,
YandexMapGeolocationControl,
YandexMapOpenMapsButton,
YandexMapScaleControl,
YandexMapZoomControl,
} from 'vue-yandex-maps';
import { computed, isRef, onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
import type { YMap } from '@yandex/ymaps3-types';
const counter = ref(1);
const timedCounter = ref(1);
const isFullscreen = ref(false);
const map = shallowRef<YMap | null>(null);
const buttons = shallowRef([
{
component: YandexMapControlButton,
content: 'first',
props: {
onClick: () => console.log('first'),
},
},
{
component: YandexMapControlButton,
content: 'foo #1',
props: {
color: '#196dff',
background: '#f3f6fc',
onClick: () => console.log('foo #1'),
},
},
{
component: YandexMapControlButton,
content: 'foo #2',
props: {
color: '#196dff',
background: '#f3f6fc',
onClick: () => console.log('foo #2'),
},
},
{
component: YandexMapControlButton,
content: 'foo #3',
props: {
color: '#196dff',
background: '#f3f6fc',
onClick: () => console.log('foo #3'),
},
},
{
component: YandexMapControlButton,
content: 'second',
props: {
onClick: () => console.log('second'),
},
},
{
component: YandexMapControlButton,
content: 'bar #1',
props: {
color: '#fff',
background: '#196dff',
onClick: () => console.log('bar #1'),
},
},
{
component: YandexMapControlButton,
content: 'bar #2',
props: {
color: '#fff',
background: '#196dff',
onClick: () => console.log('bar #2'),
},
},
{
component: YandexMapControlButton,
content: computed(() => `Control! ${ timedCounter.value }`),
},
]);
const shiftLeft = () => {
buttons.value = [...buttons.value.slice(1), buttons.value[0]];
};
const shiftRight = () => {
buttons.value = [...buttons.value.slice(-1), ...buttons.value.slice(0, -1)];
};
const updateCounter = () => {
counter.value++;
};
const toggleFullscreen = () => {
// The document.fullscreenElement returns the Element that is currently being presented in fullscreen mode in this document, or null if fullscreen mode is not currently in use
if (isFullscreen.value) {
// The document.exitFullscreen() requests that the element on this document which is currently being presented in fullscreen mode be taken out of fullscreen mode
document.exitFullscreen();
}
else {
// The element.requestFullscreen() method issues an asynchronous request to make the element be displayed in fullscreen mode
map.value!.container.requestFullscreen();
}
};
onMounted(() => {
const handleFullscreenChange = async () => {
isFullscreen.value = !!document.fullscreenElement;
};
document.addEventListener('fullscreenchange', handleFullscreenChange);
const interval = setInterval(() => {
timedCounter.value++;
if (timedCounter.value > 99) timedCounter.value = 0;
}, 1000);
onBeforeUnmount(() => {
clearInterval(interval);
document.removeEventListener('fullscreenchange', handleFullscreenChange);
});
});
css
<style scoped>
.counter {
color: #fff;
pointer-events: all;
}
.button-element {
color: #196dff;
font-weight: bold
}
.fullscreen {
width: 26px;
height: 26px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26'%3E%3Cg fill='%236B6B6B'%3E%3Cpath d='M16.14 7.86L14.27 6H20v5.7l-1.83-1.82L15.04 13 13 10.98l3.13-3.13zm0 0M9.86 18.14L11.73 20H6v-5.7l1.83 1.82L10.96 13 13 15.02l-3.13 3.13zm0 0'/%3E%3C/g%3E%3C/svg%3E");
}
.exit-fullscreen {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26'%3E%3Cg fill='%236B6B6B'%3E%3Cpath d='M8.14 15.86L6.27 14H12v5.7l-1.83-1.83-3.13 3.14L5 18.98l3.13-3.13zm0 0M17.86 10.14L19.73 12H14V6.3l1.83 1.83 3.13-3.14L21 7.02l-3.13 3.13zm0 0'/%3E%3C/g%3E%3C/svg%3E");
}
</style>