Custom control

Open in CodeSandbox

The example shows how to create custom controls. The control class must implement the IControl interface.

For faster development, you can inherit the control class from the collection.Item class.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Examples. Custom control.</title>
        <meta
            http-equiv="Content-Type"
            content="text/html; charset=UTF-8"
        />
        <!--
        Set your own API-key. Testing key is not valid for other web-sites and services.
        Get your API-key on the Developer Dashboard: https://developer.tech.yandex.ru/keys/
    -->
        <script
            src="https://api-maps.yandex.ru/2.1/?lang=en_RU&amp;apikey=<your API-key>"
            type="text/javascript"
        ></script>
        <script
            src="https://yandex.st/jquery/2.2.3/jquery.min.js"
            type="text/javascript"
        ></script>
        <script src="custom_control.js" type="text/javascript"></script>
        <style type="text/css">
            html,
            body,
            #map {
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
            }

            .customControl {
                background-color: #fff;
                padding: 10px;
                border-radius: 3px;
                max-width: 200px;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            }
        </style>
    </head>
    <body>
        <div id="map"></div>
    </body>
</html>
ymaps.ready(function () {
    /**
     * An example implementation of a custom control based on inheritance from collection.Item.
     * The control displays the name of the object that is in the center of the map.
     */
    var map = new ymaps.Map("map", {
            center: [55.819543, 37.611619],
            zoom: 6,
            controls: [],
        }),
        // Creating a custom class.
        CustomControlClass = function (options) {
            CustomControlClass.superclass.constructor.call(this, options);
            this._$content = null;
            this._geocoderDeferred = null;
        };
    // And inheriting it from the collection.Item.
    ymaps.util.augment(CustomControlClass, ymaps.collection.Item, {
        onAddToMap: function (map) {
            CustomControlClass.superclass.onAddToMap.call(this, map);
            this._lastCenter = null;
            this.getParent()
                .getChildElement(this)
                .then(this._onGetChildElement, this);
        },

        onRemoveFromMap: function (oldMap) {
            this._lastCenter = null;
            if (this._$content) {
                this._$content.remove();
                this._mapEventGroup.removeAll();
            }
            CustomControlClass.superclass.onRemoveFromMap.call(
                this,
                oldMap
            );
        },

        _onGetChildElement: function (parentDomContainer) {
            // Creating an HTML element with the text.
            this._$content = $(
                '<div class="customControl"></div>'
            ).appendTo(parentDomContainer);
            this._mapEventGroup = this.getMap().events.group();
            // Requesting data after changing the position of the map.
            this._mapEventGroup.add(
                "boundschange",
                this._createRequest,
                this
            );
            // Immediately requesting the name of the place.
            this._createRequest();
        },

        _createRequest: function () {
            var lastCenter = (this._lastCenter = this.getMap()
                .getCenter()
                .join(","));
            // Requesting information about the place by the coordinates of the map center.
            ymaps
                .geocode(this._lastCenter, {
                    // Specifying that the response should be in JSON format.
                    json: true,
                    // Setting a limit on the number of records in the response.
                    results: 1,
                })
                .then(function (result) {
                    // We will only process the response from the last request.
                    if (lastCenter == this._lastCenter) {
                        this._onServerResponse(result);
                    }
                }, this);
        },

        _onServerResponse: function (result) {
            /**
             * The data has been received from the server and now it must be displayed.
             * Description of the response in JSON format.
             */
            var members = result.GeoObjectCollection.featureMember,
                geoObjectData =
                    members && members.length ? members[0].GeoObject : null;
            if (geoObjectData) {
                this._$content.text(
                    geoObjectData.metaDataProperty.GeocoderMetaData.text
                );
            }
        },
    });

    var customControl = new CustomControlClass();
    map.controls.add(customControl, {
        float: "none",
        position: {
            top: 10,
            left: 10,
        },
    });
});