Поддержка
E-mail
Имя
Тема
Суть проблемы
Загрузить

Gradoservice
developers community
Авторизация
Close
Авторизация
Забыли пароль?
Регистрация
или
Регистрация
  • Главная
  • Статьи
  • Документация
  • Продукты
Поддержка
You are here: Home / 2013 / Май / 29 / Написание модуля «районы» для mapSurfer

Написание модуля «районы» для mapSurfer

29 мая 2013 admin

В данной статье будет рассмотрено создание модуля «районы» для mapSurfer.

районы

Выполнение модуля начинается с создания экземпляра класса GP.Controller.DistrictsController, который наследуется от GP.Controller.

GP.Module.Controller.Districts = GP.Controller.extend({...});

В котором описываются пути относительно основного проекта, по которым будут обрабатываться http запросы и лежать картинки:

statics: {
    BASE_PATH: "/modules/districts/",    //путь для запросов
    IMAGE_PATH: "/public/modules/districts/images/"    путь для картинок
},

Далее описывается конструктор контроллера:

initialize: function() {
    GP.Controller.prototype.initialize.call(this,{}); //вызов конструктора родителя,
                                                  //обязательно для контроллеров
    this._loadDistricts(); //действия модуля
},

В контроллере GP.Controller.DistrictsController GET запросом на url ‘/modules/districts/districtsList’ получаем список районов в формате json,

_loadDistricts: function(){
    $.ajax({
        type: 'GET',  //тип запроса      
        url: GP.Module.Controller.Districts.BASE_PATH+'list', //url, на который отправляется запрос
        success: M.Util.bind(this._saveToStore,this), //функция, выполняемая при
                                                   // успешном выполнении запроса
        error: function(data){   //функция, выполняемая при возникновении
                                 //ошибки обработки запроса
               }
    });
},

Для хранения данных удобно использовать Store.
В первую очередь нужно создать модель, в которой необходимо описать все составляющие элементов стора.

GP.Model.DistrictsModel = GP.Model.extend({
   fields: [
      { 
        name: "id", //имя поля
        type: "integer", //тип значений поля
        dvalue: 0, //значение по умолчанию
        notNull: true, //может ли поле быть undefined, если false то да
        rusName: "Id" //русское название
      },
      {name: "title", type: "string", dvalue: "", notNull:true, rusName: "title"},
      {name: "subTitle", type: "string", dvalue: "", notNull:true, rusName: "subTitle"},
      {name: "geom", type: "object", dvalue: "", notNull:true, rusName: "geom"},
      {name: "districtFields", type: "object", dvalue: [], notNull:true, rusName: "fields"},
      {name: "bbox", type: "object",dvalue: "", notNull:true,rusName:"bBox"}
   ]
});

Следующим шагом нужно описать стор.

GP.Store.DistrictsStore = GP.Store.extend({
    model: GP.Model.DistrictsModel
});

Затем, на основе полученных данных создается GP.stores.districtsStore (экземпляр класса GP.Store.DistrictsStore, GP.Store.DistrictsStore – класс хранилища данных, удовлетворяющих модели, описанной в GP.Model.DistrictsModel):

_saveToStore: function(data){
    GP.stores.districtsStore = new GP.Module.Store.Districts(data.districts);
    /* в переменной data.districts хранится массив,
       каждый элемент которого удовлетворяет  моделе GP.Model.DistrictsModel*/
    ...
}

Следующим шагом добавляем вкладку с районами в правую панель:

GP.widgets.tabs.addTab({
    name : "Районы", //надпись, выводимая при наведении
    image : GP.Module.Controller.Districts.IMAGE_PATH + "/icons/district.png", //иконка, отображаемая,
                                      // когда вкладка неактивна
    imageWhite : GP.Module.Controller.Districts.IMAGE_PATH + "/icons/district-white.png", //иконка,
                                          // отображаемая, когда вкладка активна
    divId : "districtsList-block"}); //id, присваиваемый элементу вкладки

Далее происходит создание виджета, ответственного за прорисовку внутренности вкладки

GP.widgets.districtsList = new GP.Widget.DistrictsList({mainDivId:"districtsList-block"});

Функция _resize класса GP.Widget.DistrictsList выполняется при изменении размеров правой панели, то есть при срабатывании события «tab:resze».

GP.widgets.tabs.on("tab:resize",this._resize,this);//выполнять функцию this._resize
                                   // при срабатывании события "tab:resze"
_resize: function(){
    var cHeight = this._mainElement.height() - 6;  //вычисление высоты элемента
                                //относительно родительского элемента, высота которого уже изменилась 
    this._blockElement.css("height",cHeight);   //установка высоты элементу
    setTimeout(M.Util.bind(function(){
        this._districtsElement.mCustomScrollbar("update");  //обновление полосы прокрутки
    },this), 300);
}

При нажатии на выбранный район создается левая панель:

self._districtInfo = new GP.Widget.DistrictsLeftPanel({
     districtId: data.data.id}, //id выбранного района
     "#wrap") //id элемента, в который поместить левую панель

Если же панель уже создана, то просто меняется содержимое:

self._districtInfo.setDistrict(data.data.id).

Класс GP.Widget.DistrictsLeftPanel наследуется от GP.Widget.LeftPanel. После создания классом GP.Widget.LeftPanel левой панели будет выполняться функция _createContent, которую мы в своем классе GP.Widget.DistrictsLeftPanel переопределяем для отрисовки нужной нам информации.

Для создания и отображения слоя с районом на карте используется функция:

_drawLayer: function(){
    var geom = GP.stores.districtsStore.getById(this._districtId).get("geom");//достаем геометрию из store
    /* переменная geom - строка, содержащая в себе данные в формате GeoJSON */
    var object = jQuery.parseJSON(geom); //создаем json объект из строки
    this._layer = new M.GeoJSON(object); //создаем слой из геометрии
    GP.mainMap.map.addLayer(this._layer); //добавляем слой на карту
    var bbox = GP.stores.districtsStore.getById(this._districtId).get("bbox");
    GP.mainMap.setBBox(bbox.minX,bbox.minY,bbox.maxX,bbox.maxY,bbox.projection); //переходим
                                   //к выбранному району на карте, устанавливая карте bBox
}

Для того, чтобы убрать слой с карты необходимо выполнить следующую функцию:

GP.mainMap.map.removeLayer(this._layer)   // this._layer – слой, который нужно убрать.

Серверная часть

Файл geoportal.modules.districts.routes. В этом файле содержатся соответствия адесов для http запросов и контроллеров, которые будут обрабатывать запросы.

тип запросапуть относительно корня модуля, по которому будут обрабатываться запросы. Итоговый путь относительно всего сайта будет выглядеть следующим образом: /modules/districts/listфункция, обрабатывающая запросы по данному пути.

GET /list controllers.geoportal.modules.districts.
Application.getListDistricts

База данных.
В базе данных находятся 3 таблицы, которые нам предстоит использовать:

1) «districts_config», находящаяся в схеме «districts». За работу с этой таблицей отвечает класс модель, который описывается следующим образом:

@Entity //аннотация Ebean, означающая ,что класс будет взаимодействовать с БД
@Table(schema = "districts", name = "districts_config")  //аннотация Ebean,
   // указывающая схему и таблицу в БД, с которой класс будет сопоставляться
public class DistrictsConfig {
...
}

2) «districts_fields», находящаяся в схеме «districts». За работу с этой таблицей отвечает класс модель, который описывается следующим образом:

import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(schema = "districts", name = "districts_fields")
public class DistrictsFields {
    @Id    //аннотация Ebean, означающая, что переменная будет являться primary key
    private Long id;
    ...
    ...
    /* переменная find нужна для писка данных из таблицы, соответствующей данному классу в БД */
    public static Model.Finder<Long,DistrictsFields> find = 
                                                         new Model.Finder(Long.class, DistrictsFields.class);
}

3) таблица, название которой заранее неизвестно, за взаимодействие с этой таблицей отвечает класс Districts.java — класс — модель, создаваемый на основе sql запроса

@Entity
@Sql   //аннотация Ebean, означающая, что экземпляр класса будет создаваться 
       // на основе sql запроса
public class District extends Model {

    @Id
    private Long id;

    private Geometry geom; //связь com.vividsolutions.jts.geom.Geometry и геометрией в бд

    private List districtFields;
    
    /* при парсинге экземпляра класса в json, список полей района будет сортироваться */
    public List getDistrictFields() { 
        DistrictField.sort(districtFields);
        return districtFields;
    }
    
    /* при парсинге экземпляра класса в json, поле с геометрией будет парситься 
       с помощью org.geotools.geojson.geom.GeometryJSON */
    public String getGeom() {
        GeometryJSON geometryJSON = new GeometryJSON();
        String geomJson = geometryJSON.toString(geom);
        return geomJson;
    }

    public static List findDistrict(DistrictsConfig districtConfig) {

        /* подготовка данных для запроса */
        String title = StringUtils.buildString(districtConfig.getTitleColumn(), " as title ");
        String subTitle = StringUtils.buildString(districtConfig.getSubtitleColumn(), " as subTitle ");
        String idColumn = StringUtils.buildString(districtConfig.getIdColumn());
        String geom = StringUtils.buildString(districtConfig.getGeomColumn(), " as geom");
        String tables = StringUtils.buildString(districtConfig.getInfoTable());
        String orderBy = districtConfig.getOrderBy();

        /* поиск всех записей в таблице districts_fields 
           (название и расположение полей с информацией о районе в основной таблице)  */
        List districtsFieldsList = DistrictsFields.find.all();

        /* подготовка sql запроса */
        String sqlSelect = StringUtils.buildString("SELECT ", title, ", ", subTitle, ", ", idColumn, " as id , ", geom,
 " FROM ", tables, " ORDER BY ", orderBy);

        /* создание экземпляра класса District на основе sql запроса  */
        RawSQLFinder find = new RawSQLFinder(District.class, sqlSelect, null);
        Query finder = find;
        List districtList = finder.findList();

        /* формирование полей с дополнительной информацией о районе 
           (напр. насиление, глава района и т.д) */
        for (District district : districtList) {
            district.setDistrictFields(new ArrayList());
            String id = district.getId().toString();

            String fieldColumns = "";
            for (DistrictsFields districtsFields : districtsFieldsList) {
                if (fieldColumns.equals(""))
                    fieldColumns = districtsFields.getFieldColumn();
                else {
                    fieldColumns = StringUtils.buildString(fieldColumns, ",", districtsFields.getFieldColumn());
                }
            }

            String sqlFieldSelect = StringUtils.buildString("SELECT ", fieldColumns, " FROM ", tables, " WHERE ",
                    idColumn, "=", id);
            List sqlFieldRows = Ebean.createSqlQuery(sqlFieldSelect).findList();
            for (SqlRow sqlFieldRow : sqlFieldRows) {
                for (DistrictsFields districtsFields : districtsFieldsList) {
                    district.districtFieldsAdd(new DistrictField(districtsFields.getFieldLabel(),
                            sqlFieldRow.getString(districtsFields.getFieldColumn()), 
                            districtsFields.getOrder(),districtsFields.getHideIfNull()));
                }
            }

        }
        return districtList;
    }
}

Контроллер Application.java.

Класс Application.java наследуется от Abstract, так как в этом абстрактном классе содержатся вспомогательные функции, которые нам пригодятся.

public class Application extends Abstract {

   public static Result getListDistricts() {

      try{
         List districtsConfigList = DistrictsConfig.find.all(); //поиск всех элементов в таблице
                                                                // districts_config

         List items = new ArrayList();
         for (DistrictsConfig districtsConfig : districtsConfigList) {
            items = District.findDistrict(districtsConfig); //составление списка районов
         }
         ObjectNode result = Json.newObject();

         result.put("districts", Json.toJson(items)); //парсинг данных в json
         return crossdomain( //функция crossdomain реализована в классе Abstract
            ok(result).as("Content-Type: application/json; charset=UTF-8")); //возвращение клиенту 
                                                          //подготовленный json объект с кодом 200
      }catch (Exception e){
         return crossdomain(internalServerError(e.getMessage()).
as("Content-Type: application/json; charset=UTF-8")); //возвращение ошибку в случае ее возникновения
      }
   }
}

Posted in mapSurfer, Статьи Tagged mapSerfer, mapSurfer, Модули

Нажмите здесь, чтобы отменить ответ.

Для добавления комментариев пожалуйста, Войдите на сайт с паролем или Зарегистрируйтесь

← Previous Next →
  • Главная
  • Статьи
  • Документация
  • Продукты
Поддержка

Copyright © 2005-2025 Gradoservice™. All rights reserved