The ability to deal with input events is an important part of your application.
LuciadRIA provides built-in controls for the most common tasks, such as panning and zooming on a map.
These controls are automatically enabled when you create a new Map
.
By default, you get the following behavior on a Map
, implemented by DefaultController
:
Mouse | Touch device | Result | API class |
---|---|---|---|
Drag the left or middle mouse button |
Drag a single finger |
Pans the map |
|
Drag the right mouse button around the center of a 2D map |
Two-finger twist gesture |
Rotates the 2D map |
|
Drag the right mouse button left and right on a 3D map |
Two-finger twist gesture |
Rotates the 3D map |
|
Drag the right mouse button up and down on a 3D map |
Two-finger drag up and down |
Pitches the 3D map |
|
Scroll |
Two-finger pinch gesture |
Zooms the map |
|
Scroll with SHIFT key held down |
None |
Zooms the map slowly |
|
Click on selectable object |
Tap on selectable object |
Selects the object |
|
Click on selectable object, with SHIFT key held down |
/ |
Adds or removes the object from the current selection |
|
Right-click on selectable object |
"Long press" on selectable object |
Opens a context menu |
|
Move mouse over hoverable object |
/ |
Make the object hovered |
|
Double-click with left mouse button |
Double tap |
Zooms in at the clicked / tapped location |
|
Double-click with right mouse button |
/ |
Zooms out from the clicked location |
You can override this default behavior by implementing a custom Controller
.
In the LuciadRIA API, the Controller
class deals with input events from the user.
You can activate and de-activate controllers by setting the Map.controller
and Map.defaultController
properties.
Map.defaultController
is typically set to controllers that deal with navigation, hovering and selection, like the ones in Table 1, “Default controller behavior”.
These remain active throughout the lifetime of the map.
By contrast, Map.controller
is typically set to controllers that deal with shorter, more specialized interactions:
creating or editing a Feature
or performing a measurement, for example.
If an input event isn’t handled by Map.controller
, it gets passed to Map.defaultController
.
For example, if your EditController
doesn’t handle a scroll event, the scroll event triggers the the default zoom behavior.
When you set these properties, you de-activate any controller that was configured before, and activate the newly configured
controller.
The controllers get notified of this state change through the Controller.onDeactivate()
and Controller.onActivate()
methods.
In this tutorial, we describe some Controller
implementations in the LuciadRIA API.
You can also create your own custom controllers to handle custom user interaction.
See Implementing custom user interaction for more information.
Creating new vector features using the CreateController
The CreateController
class makes it possible to start an interactive session of vector feature creation.
By default, users can place feature vertices through mouse clicks or free-hand drawing. You can configure the drawing mode and the minimum and maximum number of points to determine the actions you expect from the user.
For your convenience, LuciadRIA provides a concrete implementation, BasicCreateController
.
This controller implements Createcontroller.onCreateNewObject()
by creating a new shape based on a shape type token passed to its constructor.
It also wraps the shape in a Feature
instance.
This is an illustration of the usage of the BasicCreateController
class:
BasicCreateController
(from samples/createedit/main.js
)
const createController = new BasicCreateController(shapeType, {}, {
finishOnSingleClick: true
});
See the sample CreateController
in samples/common/ui/CreateShapeToolbar.tsx
and samples/symbology/cop/ObjectWithUUIDCreateController.ts
for complete illustrations.
Editing existing vector features
Graphical editing
To begin an editing session, use an EditController
.
During a graphical editing session, users can change the shape position by dragging the shape.
They can also change the shape geometry by dragging one of its vertices. Vertices automatically snap to other objects when they get close to them. To turn off snapping while editing, users can hold down the Ctrl-key.
They can also insert new points by activating one of the control points located between the vertices of a shape.
User can also delete vertices from the shape. Depending on the device they’re using, they can delete a point by pressing and holding a control point, or by pressing the Ctrl-key and clicking the control point. In a desktop environment, users can also right-click a control point and select Delete from the pop-up menu.
When a user is editing an object, a commit is performed only at the end of an editing session. This prevents overly frequent updates of the Store during editing. |
WebGL maps support editing in 2D and 3D. Only 2D shapes or 2D aspects of 3D shapes are editable. For example, you can edit only the base shape of an extruded shape. |
Textual editing of vector features via the context menu
You can execute custom actions from the context menu. This is the menu that pops up when a user right-clicks an object. Those actions are typically used for editing or changing textual properties of a domain object.
You can add actions to any FeatureLayer
by implementing the onCreateContextMenu
method.
See the Create and edit
sample for example implementations of FeatureLayer.onCreateContextMenu
.
Customizing the default map behavior
You can override the default behavior by setting a new Map.defaultController
.
You can use DefaultController
and the controllers in @luciad/ria/view/controller
to mimic,
or completely customize, the default map behavior:
// a PanController without inertia
class CustomPanController extends PanController {
isInertia(gestureEvent: GestureEvent): boolean {
return false;
}
}
// a select controller that only allows selection by clicking on labels
class CustomSelectController extends SelectController {
getPaintRepresentations(event: GestureEvent): PaintRepresentation[] {
return [PaintRepresentation.LABEL];
}
}
const navigateController = new NavigateController({
panController: new CustomPanController(),
rotateController: null // disable rotation
// default zoom (zoomController is undefined)
});
map.defaultController = new DefaultController({
selectController: new CustomSelectController(),
contextMenuController: new ContextMenuController(),
navigateController,
// default hover (hoverController is undefined)
});
If you want to prevent the default behavior completely, you can set Map.defaultController
to null
on the map.
This prevents all default behavior.
map.defaultController = null; // prevent _all_ default map behavior
Combining multiple controllers
You can combine multiple controllers with a CompositeController
.
This controller allows you to chain multiple controllers together, one after the other.
The CompositeController
forwards onGestureEvent
calls down the chain, until the first controller
in the chain handles the event.
The order of the controllers in the chain is important. To avoid issues with |
If a CompositeController
does not suffice, you can also implement your own Controller
that delegates to specific Controller
classes, using custom logic.