1. Введение
В первом уроке мы создали базовое ГИС-приложение OpenMap, которое отображает карту с одним слоем фигур , загруженным из файловой системы, внутри JFrame
. Этот учебник был основан на com.bbn.openmap.app.example.SimpleMap
. Во втором уроке мы расширили наше базовое приложение для использования MapHandler
а в третьем уроке мы увидели, как оно использует openmap.properties
для соединения всего вместе. В этом уроке мы поговорим о слоях карты.
2. Обзор слоев карты
В уроке 1 мы увидели, как добавить ShapeLayer
в MapBean
. OpenMap поддерживает большое количество типов слоев, которые можно добавить в MapBean
как показано на рисунке 1 .
BufferedLayerMapBean
— это MapBean
который использует BufferedLayer
(см. Рисунок 1 ) для создания изображения для некоторых слоев. Он использует флаг фона Layer
чтобы определить, какие слои следует добавить к этому буферизованному изображению. Любой слой, который не отвечает на MouseEvent
должен быть обозначен как фоновый слой, чтобы уменьшить нагрузку при обработке метода paint()
на приложение.
OMGraphicHandlerLayer
— это класс базового уровня, который реализует наиболее распространенную функциональность уровня, который должен взаимодействовать и совместно использовать OMGraphic
. GraticuleLayer
создает свои OMGraphic
внутри, а ShapeLayer
считывает данные из файла. DTEDLayer
и RpfLayer
имеют кэши изображений. Существуют специальные слои, которые позволяют вам получить доступ к пространственной базе данных для создания OMGraphic
. Любая техника управления графикой может быть использована внутри слоя.
Как базовый класс, OMGraphicHandlerLayer
имеет встроенные возможности, которые облегчают управление OMGraphic
в слое. Расширяя OMGraphicHandlerLayer
, реализуйте метод prepare()
чтобы вернуть OMGraphicList
содержащий OMGraphic
s, соответствующий проекции, установленной в данный момент в слое. Вся работа по сбору, подготовке и генерации OMGraphic
должна выполняться в методе prepare()
. OMGraphicHandlerLayer
также имеет встроенный объект SwingWorker
который можно использовать для вызова prepare()
в отдельном потоке. Поток SwingWorker
можно запустить, вызвав метод doPrepare()
. Если SwingWorker
уже занят при doPrepare()
метода doPrepare()
, новый поток будет запущен для вызова prepare()
после завершения исходного потока. В стандартной реализации метода prepare()
текущий список просто генерируется с текущей проекцией и возвращается.
Пожалуйста, обратитесь к руководству разработчика для получения дополнительной информации о том, как использовать эти слои.
OpenMap также предоставляет несколько слоев для обучения ( com.bbn.openmap.layer.learn
):
- BasicLayer
- InteractionLayer
- SimpleAnimationLayer
- ProjectionResponsiveLayer
а также тестовые слои ( com.bbn.openmap.layer.test
):
- BoundsTestLayer
- GeoCrossDemoLayer
- GeoIntersectionLayer
- GeoTestLayer
- HelloWorldLayer
- TestLayer
Наконец, com.bbn.openmap.layer.DemoLayer
является примером того, как слой может использовать OMDrawingTool
для редактирования OMGraphic
. Он использует инструмент рисования для создания областей на карте, которые используются в качестве фильтров для управления тем, какие из его OMGraphic
также видны.
Слои происходят от java.awt.Component
и они являются единственными компонентами, которые могут быть добавлены в MapBean
. Поскольку MapBean
— это Component
содержащиеся в контейнере MapBean
, рендеринг Layer
на карту контролируется механизмом рендеринга компонентов Java. Этот механизм контролирует, как слоистые компоненты окрашены друг на друга. Чтобы убедиться, что каждый компонент отображается в окне в правильном порядке, класс Component
включает метод, который позволяет ему сообщать механизму рендеринга, что он хотел бы быть нарисованным. Эта функция позволяет слоям работать независимо друг от друга и позволяет MapBean
не знать, что происходит на MapBean
.
Слои в приложении OpenMap могут использовать данные из многих источников:
- Вычисляя их
- Из файлов данных локального жесткого диска
- Из файлов данных из URL
- Из файлов данных, содержащихся в jar-файле
- Использование информации, полученной из базы данных (JDBC)
- Использование информации, полученной от картографического сервера (изображения или объекты карты)
2.1 Создание слоев
Давайте начнем с самых простых слоев. Уже из Tutorial 1 мы увидели, как создать ShapeLayer
и добавить его в MapBean
. Но начиная с Tutorial 3 мы openmap.properties
мощью openmap.properties
и MapHandler
. Вот изменения, которые вам нужно сделать.
Листинг 1 — openmap.properties
01
02
03
04
05
06
07
08
09
10
11
|
... # These layers are turned on when the map is first started. Order # does not matter here... openmap.startUpLayers=basic graticule shapePolitical # Layers listed here appear on the Map in the order of their names. openmap.layers=basic graticule shapePolitical # Basic Layer basic. class =com.bbn.openmap.layer.learn.BasicLayer basic.prettyName=Basic ... |
В качестве краткого напоминания openmap.layers
ссылается на загружаемые слои, а openmap.startUpLayers
ссылается на те, которые должны быть загружены при запуске. Вы заметите, что basic
слой был добавлен.
Результат можно визуализировать на рисунке 2. Из BasicLayer
BasicLayer мы узнаем, что он расширяет OMGraphicHandlerLayer
, который содержит хорошую функциональность, но предоставляет только методы, необходимые для начала добавления объектов ( OMGraphic
s) на карту. Это слой, в котором объекты никогда не меняются, а объекты карты, используемые этим слоем, никогда не меняются. Они всегда управляются и рисуются, даже если они находятся за пределами видимой карты. Когда проекция изменяется, OMGraphic
получают сообщение о том, что такое новая проекция, чтобы они могли изменить OMGraphic
положение, и затем они перерисовываются. Если вы хотите больше узнать о взаимодействии с вашими OMGraphic
после того, как вы OMGraphic
их эффективно отображать, перейдите на OMGraphic
InteractionLayer
.
Слои реализуют интерфейс ProjectionListener
для прослушивания ProjectionEvent
. Когда проекция изменяется, им может понадобиться повторно извлечь, восстановить их графику, а затем перерисовать себя в новом виде. Мы расскажем больше о проектировании в следующем уроке.
BasicLayer
переопределяет два метода из OMGraphicHandlerLayer
:
-
prepare()
: этот метод вызывается при добавлении слоя на карту или при изменении проекции карты. Нам нужно убедиться, чтоOMGraphicList
возвращаемый этим методом, является тем, что мы хотим нарисовать на карте.OMGraphic
должны быть сгенерированы с текущей проекцией. Мы проверяем нулевойOMGraphicList
в слое, чтобы увидеть, нужно ли нам создаватьOMGraphic
s. Этот слой не меняет своиOMGraphic
для разных проекций, если ваш слой делает это, вам нужно очиститьOMGraphicList
и добавитьOMGraphics
вы хотите для текущей проекции. -
init()
: вызывается из методаprepare()
если слой обнаруживает, что егоOMGraphicList
равенnull
.
1
2
3
4
5
6
7
8
|
public synchronized OMGraphicList prepare() { OMGraphicList list = getList(); if (list == null ) { list = init(); } list.generate(getProjection()); return list; } |
getList()
возвращает все, что было возвращено из этого метода при последнем вызове prepare()
. В этом примере мы всегда возвращаем объект OMGraphicList
, поэтому, если он null
, prepare()
не был вызван. В этом случае вызывается init()
.
Перед возвратом списка объектов карты, вызов для установки проекции слоя имеет решающее значение! OMGraphic
нужно сказать, где рисовать себя, и они OMGraphic
это, когда им передается текущая Projection
в вызове generate(Projection)
. Если OMGraphic
изменилось, его нужно будет восстановить перед тем, как он будет отрендерен, иначе он не будет отрисовываться сам. У вас может возникнуть проблема генерации, когда OMGraphic
появляются с изменениями проекции (масштабирование и панорамирование), но не в любое другое время после каких-либо изменений в OMGraphic
. Если вы хотите быть более эффективным, вы можете заменить этот вызов списка в качестве предложения else для проверки (list == null)
выше, и вызывать generate(Projection)
для всех OMGraphics в методе init()
ниже, так как вы создать их. Это предотвратит OMGraphicList.generate(Projection)
создания дополнительного цикла через все OMGraphic
прежде чем они будут возвращены.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public OMGraphicList init() { OMGraphicList omList = new OMGraphicList(); // Add an OMLine OMLine line = new OMLine(40f, -145f, 42f, -70f, OMGraphic.LINETYPE_GREATCIRCLE); // line.addArrowHead(true); line.setStroke( new BasicStroke( 2 )); line.setLinePaint(Color.red); line.putAttribute(OMGraphicConstants.LABEL, new OMTextLabeler( "Line Label" )); omList.add(line); // Add a list of OMPoints. OMGraphicList pointList = new OMGraphicList(); for ( int i = 0 ; i < 100 ; i++) { OMPoint point = new OMPoint(( float ) (Math.random() * 89f), ( float ) (Math.random() * -179f), 3 ); point.setFillPaint(Color.yellow); point.setOval( true ); pointList.add(point); } omList.add(pointList); return omList; } |
Метод init()
вызывается, когда prepare()
возвращает null
. Он создает объекты ( OMGraphic
), которые будут добавлены к слою.
В качестве краткого руководства типичное ГИС-приложение состоит из карты ( MapBean
в OpenMap), которая состоит из слоев (объектов Layer
), которые состоят из объектов ( OMGraphic
). На следующем рисунке показана иерархия классов OMGraphic
s.
Код в листинге 3 создает OMLine
и 100 OMPoint
. OMGraphic
— это объекты растровой и векторной графики, которые знают, как позиционировать и визуализировать себя в заданном окне xy или проекции карты широты. Все, что вам нужно сделать, это предоставить данные о местоположении (x / y, широта / долгота) и информацию о чертеже (цвет, ширина линии), а остальная часть обрабатывается графикой.
Это должно быть легким и хорошим началом (мы увидим, например, как мы можем отображать данные из базы данных в следующем уроке), но, как вы могли заметить, интерактивности нет. Интерактивность демонстрируется InteractionLayer
. Теперь вы должны иметь возможность заменить Basic
слой на InteractionLayer
в openmap.properties
.
InteractionLayer
демонстрирует, как взаимодействовать с вашими OMGraphic
на карте, как заставить их изменять внешний вид с помощью событий мыши и предоставлять дополнительную информацию о себе. Этот слой основан на примере, продемонстрированном в BasicLayer
.
Если вы запустите приложение, вы заметите, что, когда вы наводите курсор мыши на OMPoint, оно меняет цвет. Вы также можете щелкнуть по нему правой кнопкой мыши, чтобы открыть всплывающее меню. Мы будем использовать эту функцию для отображения свойств функции. Вы можете просмотреть com.bbn.openmap.layer.learn.InteractionLayer
самостоятельно. Я просто OMGraphicHandlerLayer
здесь несколько кратких рекомендаций о том, как добавить взаимодействия к вашему OMGraphicHandlerLayer
. Не забудьте добавить эту строку в конструктор:
Листинг 4 — setMouseModeIDsForEvents ()
1
2
3
4
5
6
7
8
|
// Making the setting so this layer receives events from the // SelectMouseMode, which has a modeID of "Gestures". Other // IDs can be added as needed. You need to tell the layer which // MouseMode it should listen to, so it can tell the MouseModes to send // events to it. // Instead of "Gestures", you can also use SelectMouseMode.modeID or // OMMouseMode.modeID setMouseModeIDsForEvents( new String[] { SelectMouseMode.modeID }); // "Gestures" |
Это фактически говорит вашему слою, что его функции должны реагировать на жесты мыши (например, наведение мыши). MouseEvent
может управляться некоторыми компонентами OpenMap, направляя их на слои и на OMGraphic
. MouseMode
описывает, как MouseEvent
и MouseMotionEvent
интерпретируются и используются. MouseDelegator
— это настоящий MouseListener
и MouseMotionListener
в MapBean
. MouseDelegator
управляет списком MouseMode
и знает, какой из них является «активным» в любой момент времени. MouseDelegator
также запрашивает у активных слоев свои MapMouseListener
и добавляет те, которые заинтересованы в событиях из активного MouseMode
качестве слушателей этого режима.
Когда MouseEvent
запускается из MapBean, он проходит через MouseDelegator
в активный MouseMode
, где MouseMode
начинает предоставлять MouseEvent
своим MapMouseListener
. Каждому слушателю предоставляется возможность использовать событие. MapMouseListener
может воздействовать на событие и не использовать его, чтобы его можно было продолжать передавать другим слушателям.
MapMouseListener
предоставляет массив String всех MouseMode ID
от MouseMode ID
он заинтересован в получении событий, а также имеет свои собственные методы, в MouseMotionEvent
поступают MouseEvent
и MouseMotionEvent
. MapMouseListener
может использовать эти события в сочетании с OMGraphicList
, чтобы найти out, если события произошли на каком-либо OMGraphic
, и ответить, если необходимо.
Есть несколько MouseModes
которыми ваш слой может взаимодействовать. Поиск modeID
в исходном коде или здесь возвращает следующие 8 режимов мыши (есть два дубликата):
-
DistanceMouseMode.modeID = "Distance"
-
DistQuickToolMouseMode.modeID = "Distance"
-
NavMouseMode.modeID = "Navigation"
-
NullMouseMode.modeID = "None"
-
OMDrawingToolMouseMode.modeID = "Drawing"
-
OMMouseMode.modeID = "Gestures"
-
PanMouseMode.modeID = "Pan"
-
RangeRighsMouseMode.modeID = "RangeRings"
-
SelectMouseMode.modeID = "Gestures"
-
ZoomMouseMode.modeID = "Zoom"
Не забудьте добавить что-то вроде следующего к вашим функциям при их создании, для визуального отображения, когда на них point.setSelectPaint(Color.yellow);
курсор мыши: point.setSelectPaint(Color.yellow);
Вы можете переопределить следующие методы:
-
isSelectable()
— Запрос о том, чтоOMGraphic
можно выбрать. Вы должны вернутьtrue
чтобы сделать его доступным для выбора. -
isHighlightable()
— Запрос, чтоOMGraphic
может быть выделен, когда мышь перемещается над ним. -
getInfoText()
— отображать текст в строке состояния, когда указатель мыши находится надOMGraphic
-
getToolTipTextFor()
— отображать всплывающую подсказку, когда мышь находится надOMGraphic
Например
Листинг 5 — методы взаимодействия
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/** * Query that an OMGraphic can be highlighted when the mouse moves over it. * If the answer is true, then highlight with this OMGraphics will be * called, and unhighlight will be called with the mouse is moved off of it. * * @see com.bbn.openmap.layer.OMGraphicHandlerLayer#highlight * @see com.bbn.openmap.layer.OMGraphicHandlerLayer#unhighlight */ public boolean isHighlightable(OMGraphic omg) { return true ; } /** * Query that an OMGraphic is selectable. Examples of handing selection are * in the EditingLayer. The default OMGraphicHandlerLayer behavior is to add * the OMGraphic to an OMGraphicList called selectedList. If you aren't * going to be doing anything in particular with the selection, then return * false here to reduce the workload of the layer. * * @see com.bbn.openmap.layer.OMGraphicHandlerLayer#select * @see com.bbn.openmap.layer.OMGraphicHandlerLayer#deselect */ public boolean isSelectable(OMGraphic omg) { return true ; } |
Если вы хотите отобразить всплывающее меню при щелчке правой кнопкой мыши на OMGraphic
, переопределите следующий метод для возврата списка пунктов меню. В будущем уроке мы будем использовать этот метод для отображения свойств объекта из базы данных.
-
List getItemsForOMGraphicMenu(OMGraphic omg)
Если вы хотите отобразить всплывающее меню при щелчке правой кнопкой мыши в любом месте слоя, переопределите следующий метод, чтобы получить список пунктов меню:
-
List getItemsForMapMenu(MapMouseEvent me)
Надеюсь, это было довольно мило и не так сложно, однако вы не можете перемещать функции. Например, я хотел бы иметь возможность выбрать OMPoint
и перетащить его на новую позицию. Чтобы добавить эту функциональность, нам нужно изучить некоторые слои, которые не перечислены в приведенных выше списках:
-
com.bbn.openmap.layer.DemoLayer
-
com.bbn.openmap.layer.DrawingToolLayer
-
com.bbn.openmap.layer.editor.EditorLayer
Попробуйте каждый из них. На самом деле мы видели DemoLayer
в действии в предыдущем уроке, но мы не DemoLayer
код. Итак, чтобы иметь возможность перетаскивать / изменять функции, вам необходимо:
- Реализовать интерфейс
DrawingToolRequestor
- Определите и инициализируйте экземпляр
DrawingTool
вfindAndInit()
- Изменить
isSelectable()
,getInfoText()
,getToolTipTextFor()
, соответственно - Переопределите методы
select()
иdrawingComplete()
как показано в листинге 4
Листинг 6 — Как рисовать на карте
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
public class DemoLayer extends OMGraphicHandlerLayer implements DrawingToolRequestor { protected DrawingTool drawingTool; ... public DrawingTool getDrawingTool() { // Usually set in the findAndInit() method. return drawingTool; } public void setDrawingTool(DrawingTool dt) { // Called by the findAndInit method. drawingTool = dt; } @Override public void findAndInit(Object someObj) { if (someObj instanceof DrawingTool) { setDrawingTool((DrawingTool) someObj); } } @Override public void findAndUndo(Object someObj) { if (someObj instanceof DrawingTool) { if (getDrawingTool() == (DrawingTool) someObj) { setDrawingTool( null ); } } } @Override public boolean isSelectable(OMGraphic omg) { DrawingTool dt = getDrawingTool(); return (dt != null && dt.canEdit(omg.getClass())); } @Override public String getInfoText(OMGraphic omg) { DrawingTool dt = getDrawingTool(); return (dt != null && dt.canEdit(omg.getClass())) ? "Click to edit graphic." : null ; } @Override public String getToolTipTextFor(OMGraphic omg) { Object tt = omg.getAttribute(OMGraphic.TOOLTIP); if (tt instanceof String) { return (String) tt; } String classname = omg.getClass().getName(); int lio = classname.lastIndexOf( '.' ); if (lio != - 1 ) { classname = classname.substring(lio + 1 ); } return "Your Layer Object: " + classname; } @Override public void select(OMGraphicList list) { if (list != null && !list.isEmpty()) { OMGraphic omg = list.getOMGraphicAt( 0 ); DrawingTool dt = getDrawingTool(); if (dt != null && dt.canEdit(omg.getClass())) { dt.setBehaviorMask(OMDrawingTool.QUICK_CHANGE_BEHAVIOR_MASK); if (dt.edit(omg, this ) == null ) { // Shouldn't see this because we checked, but ... fireRequestInfoLine( "Can't figure out how to modify this object." ); } } } } @Override public void drawingComplete(OMGraphic omg, OMAction action) { if (!doAction(omg, action)) { // null OMGraphicList on failure, should only occur if // OMGraphic is added to layer before it's ever been // on the map. setList( new OMGraphicList()); doAction(omg, action); } repaint(); } ... } |
Когда вы запускаете приложение, вы теперь можете выбрать и перетащить объект в новое место или изменить его геометрию (для линий, окружностей и т. Д.).
Когда вы нажимаете кнопку Drawing Tool Launcher
, вы можете добавлять на слой множество типов графики, что может оказаться не тем, что вам нужно. Например, вы можете захотеть, чтобы ваш слой отображал только OMPoint
s, и вы не хотите, чтобы пользователь мог добавлять, например, линии или круги, используя Drawing Tool
. Это может быть легко сделано, если вы измените openmap.components
оставив только omdrawingtool
и ompointloader
(или только типы загрузчиков OM, которые вы используете в своем приложении):
Листинг 7 — openmap.components, чтобы не отображать инструмент рисования (omdt)
1
|
openmap.components=menulist informationDelegator projFactory projectionstack toolBar zoompanel navpanel scalepanel projectionstacktool addlayer layersPanel overviewMapHandler layerHandler mouseDelegator projkeys coordFormatterHandler mouseModePanel mouseMode selectMouseMode navMouseMode distanceMouseMode panMouseMode omdrawingtool ompointloader |
Другая проблема заключается в том, что при щелчке правой кнопкой мыши на OMPoint
появляется всплывающее меню, отличное от того, которое вы создали с помощью getItemsForOMGraphicMenu()
.
Виновником является OMDrawingTool
. Поскольку OpenMap является проектом с открытым исходным кодом, рекомендуется прочитать код вышеуказанного класса ( com.bbn.openmap.tools.drawing.OMDrawingTool
). Собственно, в методе select()
вы увидите строку:
1
|
dt.setBehaviorMask(OMDrawingTool.QUICK_CHANGE_BEHAVIOR_MASK); |
OMDrawingTool
определяет несколько масок поведения:
-
SHOW_GUI_BEHAVIOR_MASK
-
GUI_VIA_POPUP_BEHAVIOR_MASK
-
USE_POPUP_BEHAVIOR_MASK
-
ALT_POPUP_BEHAVIOR_MASK
-
PASSIVE_MOUSE_EVENT_BEHAVIOR_MASK
-
DEACTIVATE_ASAP_BEHAVIOR_MASK
-
DEFAULT_BEHAVIOR_MASK
-
QUICK_CHANGE_BEHAVIOR_MASK
Вы можете попробовать их все, чтобы увидеть, как ведет себя слой. К сожалению, ни один из них не покрывает наши потребности. Если всплывающее окно (или наше всплывающее окно) не появляется, функция не может быть перетащена в другое место; если появляется всплывающее окно, это одно из OMDrawingTool
. Итак, хак. Мы создадим наш собственный OMDrawingTool
:
Листинг 8 — Класс MyDrawingTool
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public class MyDrawingTool extends OMDrawingTool { public MyDrawingTool() { super (); setBehaviorMask(OMDrawingTool.QUICK_CHANGE_BEHAVIOR_MASK); } @Override public JPopupMenu createPopupMenu() { JPopupMenu popup = super .createPopupMenu(); popup.removeAll(); popup.add( new JMenuItem( "Which" )); popup.add( new JMenuItem( "Why" )); return popup; } } |
Вы можете пойти еще дальше, добавив методы set, чтобы установить список JMenuItem
созданный методом getItemsForOMGraphicMenu()
, но я оставляю это как упражнение для вас. Нам нужно сделать еще одну вещь:
Листинг 9 — openmap.properties для отображения нашего инструмента рисования
1
2
|
omdrawingtool. class =openmap.MyDrawingTool #omdrawingtool. class =com.bbn.openmap.tools.drawing.OMDrawingTool |
С этим изменением вы можете удалить строку, которая устанавливает маску поведения в методе select()
вашего слоя.
Слои OpenMap также поддерживают анимацию. Замените предыдущий слой на SimpleAnimationLayer
в openmap.properties
. При повторном запуске приложения вы видите пустую карту. Нажмите на кнопку слоев и выберите свойства AnimationLayer
(см. Рисунок 5 ). В появившемся диалоговом окне добавьте спрайты, нажав соответствующую кнопку, и, когда вы будете довольны, установите флажок « Таймер запуска», чтобы увидеть их перемещение. Вы можете настроить ползунок интервала таймера, чтобы они двигались быстрее или медленнее.
Все ранее упомянутые слои расширяют OMGraphicHandlerLayer
. Но вы можете обойтись без этого. Например, взгляните на HelloWorldLayer
который переопределяет Layer
напрямую. Его createGraphics()
создает объекты и добавляет их в переданный OMGraphicList
.
TestLayer
проверить другие слои, упомянутые в начале этой статьи, такие как TestLayer
, GeoTestLayer
и т. Д.
Чтобы кнопка « Свойства» была включена в диалоговом окне «Слои» и что-то отображалось, необходимо переопределить метод getGUI()
. Смотрите, например, TestLayer
или SimpleAnimationLayer
.
3. Вывод
Этот урок был посвящен слоям OpenMap. Мы начали с простого BasicLayer
, который отображает статические данные, затем добавили взаимодействие с InteractionLayer
, продемонстрировали, как перемещать объекты в новые местоположения на карте или изменили геометрию объектов с помощью мыши, и продолжили с AnimationLayer
чтобы продемонстрировать, как анимировать объекты слоя , Мы не покрывали все. Несмотря на то, что мы видели, как добавлять и управлять функциями, мы еще не говорили о проекциях. В следующем уроке мы создадим наше первое трехуровневое приложение, в котором мы увидим, как отображать данные из базы данных на карте.