Свой контрол в OpenLayers

В этой статье мы рассмотрим, как разработать свой контрол в OpenLayers. Контрол сделаем максимально простым в части функциональности и сосредоточимся именно на механизме интеграции контрола в карту. В дальнейшем на этом фундаменте можно будет создавать контролы любого уровня сложности.


OpenLayers 3 дает значительно большую степень свободы при создании своих контролов по сравнению с предшественником. Предполагается, что даже располагать div-элемент для контрола нужно своими руками. С одной стороны, работы стало немного больше. Но с другой, что на мой взгляд более важно, у разработчика есть полный контроль над происходящим и, соответственно, ему доступно больше возможностей.

Контролом, который мы планируем создать, будет кнопка определения местоположения. В OpenLayers 2 нам бы подошел контрол с типом OpenLayers.Control.TYPE_BUTTON. Так бы библиотека понимала, что при нажатии выполняется какое-то действие и про котнрол можно забыть (в отличие от типа OpenLayers.Control.TYPE_TOGGLE, при котором кнопка залипала и контрол переходил в активный режим до повторного нажатия на кнопку). Теперь никаких типов нет. Нужна кнопка — добавьте на карту div и повесьте на него событие onclick. Нужно, чтобы кнопка залипала? Добавьте статус включен/выключен и при клике включайте или выключайте контрол в зависимости от текущего статуса (не забывая менять CSS-класс кнопке на карте). Этот дух свободы пропитывает всю библиотеку — сейчас у слоев даже имен нет! Если нужно — добавьте свойство name к экземплярам слоев (это же JavaScript, в конце концов).

Свой контрол в OpenLayers — это просто какая-то ваша функция, которая наследуется от определенного класса ol3. Код будет выглядеть примерно так:


    var GeolocationControl = function ( opt_options ) {
        var options = opt_options || {};
        
        this._element;
        
        this._init();

        ol.control.Control.call( this, {
            element: this._element,
            target: options.target
        } );
    };

    ol.inherits( GeolocationControl, ol.control.Control );

Выделенные строки — это как раз то, что заставляет быть нашу функцию контролом. this._element — это контейнер контрола, он отвечает за отображение на карте. Вся логика по созданию контрола вынесена в функцию _init, вот она:


    GeolocationControl.prototype._init = function () {
        // создаем кнопку с буквой М
        var button = document.createElement( 'button' );
        button.innerHTML = 'М';
        button.title = 'Определить местоположение';

        // вешаем события, по которым контрол начнет работу
        button.addEventListener( 'click', this._trigger.bind( this ), false );
        button.addEventListener( 'touchstart', this._trigger.bind( this ), false );

        // создаем контейнер и помещаем в него кнопку
        this._element = document.createElement( 'div' );
        this._element.className = 'ol-control ol-control-geolocation';
        this._element.appendChild( button );
    };

Здесь мы создали все необходимые DOM-элементы, назначили необходимые события и задали стили. Важно, чтобы ваши функции прототипа шли после вызова функции ol.inherits( GeolocationControl, ol.control.Control ), которая переопределяет прототип объекта и, соответственно, все функции затрутся. Здесь ol-control — это стандартный стиль, он делает наш контрол похожим на все остальные. А ol-control-geolocation — это наш персональный стиль, в нем мы задаем лишь положение контрола на карте (так как ничего другого нам не нужно):


    .ol-control-geolocation {
        bottom: .5em;
        left: .5em;
    }

Нам осталась небольшая часть, которая задает поведение контрола, рассмотрим этот фрагмент кода:


    GeolocationControl.prototype._trigger = function ( e ) {
        e.preventDefault();
        // пытаемся получить местоположение с помощью стандартного функционала HTML 5
        var geolocation = navigator.geolocation;
        if (geolocation) {
            geolocation.getCurrentPosition(this._geolocationSuccess, this._geolocationError);
        } else {
            alert("Определение местоположения недоступно");
        }
    };
    
    GeolocationControl.prototype._geolocationSuccess = function ( position ) {
        // координаты приходят в градусах
        var coordWgs = [position.coords.longitude, position.coords.latitude];
        // преобразуем градусы в метры
        var coordMercator = ol.proj.transform(coordWgs, "EPSG:4326", "EPSG:3857");
        // ... и центрируем карту по этим координатам
        map.getView().setCenter(coordMercator);
        
        alert("Ваши координаты: широта " + position.coords.latitude + ", долгота " + position.coords.longitude);
    };
    
    GeolocationControl.prototype._geolocationError = function () {
        alert("Ошибка определения местоположения");
    };

Функции снабжены комментариями, поэтому повторяться не буду. Если браузеру удалось определить координаты, он вызывает функцию _geolocationSuccess, где устанавливается центр карты в том месте, где находится пользователь (ну или близко с тем местом… ну или хотя бы в одном городе…). Конечно, в нужном положении необходимо поставить маркер, но мы этого пока не умеем, поэтому просто выводим сообщение через alert. Ну а результат работы можно посмотреть ниже (внимание на букву М в нижнем левом углу карты):




Ссылки:

Свой контрол в OpenLayers
Метки:    

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *