Создание маркера с попап окном
vanilla.html
react.html
vue.html
common.css
common.ts
<!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 {LngLat, YMapMarker} from '@yandex/ymaps3-types';
import {LOCATION, LONG_TEXT} from './common';
window.map = null;
main();
async function main() {
// Waiting for all api elements to be loaded
await ymaps3.ready;
const {YMapComplexEntity, YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker} = ymaps3;
// Import the package to add a default marker
const {YMapDefaultMarker} = await ymaps3.import('@yandex/ymaps3-markers@0.0.1');
// Create a custom marker class with a popup
interface CustomMarkerWithPopupProps {
coordinates: LngLat; // marker position [lng, lat]
popupContent: string;
zIndex?: number;
blockBehaviors?: boolean;
}
class CustomMarkerWithPopup extends YMapComplexEntity<CustomMarkerWithPopupProps> {
private _marker: YMapMarker;
private _popup: YMapMarker | null = null;
// Handler for attaching the control to the map
_onAttach() {
this._createMarker();
}
// Handler for detaching control from the map
_onDetach() {
this._marker = null;
}
// Handler for updating marker properties
_onUpdate(props: CustomMarkerWithPopupProps) {
if (props.zIndex !== undefined) {
this._marker?.update({zIndex: props.zIndex});
}
if (props.coordinates !== undefined) {
this._marker?.update({coordinates: props.coordinates});
}
}
// Method for creating a marker element
_createMarker() {
const element = document.createElement('div');
element.className = 'marker';
element.onclick = () => {
this._openPopup();
};
this._marker = new YMapMarker({coordinates: this._props.coordinates}, element);
this.addChild(this._marker);
}
// Method for creating a popup window element
_openPopup() {
if (this._popup) {
return;
}
const element = document.createElement('div');
element.className = 'popup';
const textElement = document.createElement('div');
textElement.className = 'popup__text';
textElement.textContent = this._props.popupContent;
const closeBtn = document.createElement('button');
closeBtn.className = 'popup__close';
closeBtn.textContent = 'Close Popup';
closeBtn.onclick = () => this._closePopup();
element.append(textElement, closeBtn);
const zIndex = (this._props.zIndex ?? YMapMarker.defaultProps.zIndex) + 1_000;
this._popup = new YMapMarker({
coordinates: this._props.coordinates,
zIndex,
// This allows you to scroll over popup
blockBehaviors: this._props.blockBehaviors
}, element);
this.addChild(this._popup);
}
_closePopup() {
if (!this._popup) {
return;
}
this.removeChild(this._popup);
this._popup = null;
}
}
// 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},
[
// Add a map scheme layer
new YMapDefaultSchemeLayer({}),
// Add a layer of geo objects to display the markers
new YMapDefaultFeaturesLayer({})
]
);
map
// Add a default marker with a popup window from the package to the map
.addChild(
new YMapDefaultMarker({
coordinates: [37.9, 55.85],
color: '#006efc',
popup: {content: 'Popup on the default marker', position: 'left'}
})
)
// Add a custom marker with a popup window to the map
.addChild(new CustomMarkerWithPopup({coordinates: [37.32, 55.57], popupContent: 'Popup on the custom marker (not scrollable)'}))
.addChild(new CustomMarkerWithPopup({coordinates: [37.74, 55.43], popupContent: LONG_TEXT, blockBehaviors: true}));
}
</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 {LngLat} from '@yandex/ymaps3-types';
import {LOCATION, LONG_TEXT} 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, YMapDefaultFeaturesLayer, YMapMarker} = reactify.module(ymaps3);
const {useState} = React;
// Import the package to add a default marker
const {YMapDefaultMarker} = reactify.module(await ymaps3.import('@yandex/ymaps3-markers@0.0.1'));
function App() {
return (
// Initialize the map and pass initialization parameters
<YMap location={LOCATION} showScaleInCopyrights={true} ref={(x) => (map = x)}>
{/* Add a map scheme layer */}
<YMapDefaultSchemeLayer />
{/* Add a layer of geo objects to display the markers */}
<YMapDefaultFeaturesLayer />
{/* Add a default marker with a popup window from the package to the map */}
<YMapDefaultMarker
coordinates={[37.9, 55.85]}
color="#006efc"
popup={{content: 'Popup on the default marker', position: 'left'}}
/>
{/* Add a custom marker with a popup window to the map */}
<CustomMarkerWithPopup
coordinates={[37.32, 55.57]}
popupContent="Popup on the custom marker (not scrollable)"
/>
<CustomMarkerWithPopup coordinates={[37.74, 55.43]} popupContent={LONG_TEXT} blockBehaviors />
</YMap>
);
}
// Create a custom marker component with a popup
interface CustomMarkerWithPopupProps {
coordinates: LngLat; // marker position [lng, lat]
popupContent: string;
zIndex?: number;
blockBehaviors?: boolean;
}
function CustomMarkerWithPopup(props: CustomMarkerWithPopupProps) {
const [popupOpen, setPopupOpen] = useState(false);
return (
<>
<YMapMarker coordinates={props.coordinates}>
<div className="marker" onClick={() => setPopupOpen(true)}></div>
</YMapMarker>
{/**
* Create or delete a popup using conditional rendering.
* `YMapMarker.blockBehaviors` prop allows you to scroll over popup.
*/}
{popupOpen && (
<YMapMarker
coordinates={props.coordinates}
zIndex={(props.zIndex ?? ymaps3.YMapMarker.defaultProps.zIndex) + 1_000}
blockBehaviors={props.blockBehaviors}
>
<div className="popup">
<div className="popup__text">{props.popupContent}</div>
<button className="popup__close" onClick={() => setPopupOpen(false)}>
Close Popup
</button>
</div>
</YMapMarker>
)}
</>
);
}
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>
<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"></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>
.marker {
width: 25px;
height: 25px;
cursor: pointer;
border: 10px solid #006efc;
border-radius: 50%;
background-color: #fff;
transform: translate(-50%, -50%);
}
.popup {
position: absolute;
display: flex;
overflow: scroll;
flex-direction: column;
align-items: center;
width: 150px;
max-height: 150px;
padding: 20px 25px;
border: 2px solid #000;
border-radius: 7px;
background: #fff;
box-shadow: 0 0 8px 0 #0003;
transform: translate(30px, -220px);
gap: 20px;
overscroll-behavior: contain;
touch-action: pan-y;
}
.popup__text {
font-size: 20px;
font-weight: 600;
white-space: break-spaces;
}
.popup__close {
padding: 7px;
font-size: 16px;
cursor: pointer;
color: #fff;
border: none;
border-radius: 7px;
outline: none;
background-color: rgb(253, 100, 102);
transition: background-color 0.2s;
}
.popup__close:hover {
background-color: rgb(253, 80, 80);
}
.popup__close:active {
background-color: rgb(253, 100, 102);
}
import type {YMapLocationRequest} from '@yandex/ymaps3-types';
export const LOCATION: YMapLocationRequest = {
center: [37.623082, 55.75254], // starting position [lng, lat]
zoom: 9 // starting zoom
};
export const LONG_TEXT =
'Popup on the custom marker (scrollable)\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';