To define a Proj4Crs
(custom CRS) you have to register a projection of proj4.Projection
. For that you must import proj4dart
library as follows:
You can create and register your custom projection in multiple ways, but the recommended is to use a Proj4 definition string from epsg.io. For example for EPSG:3413
(WGS 84 / NSIDC Sea Ice Polar Stereographic North) you can find it here. This is how a Proj4 definition string looks like:
With this Proj4 definition string and a string identifier register your proj4.Projection
like this:
For more possible ways to register proj4.Projection
see proj4dart documentation.
You can use your previously registered proj4.Projection
to create a custom CRS of type Proj4Crs
. You can use the following parameters:
<String>
code
(required): string identifier for the selected CRS, e.g. EPSG:3413
<proj4.Projection>
proj4Projection
(required): the proj4.Projection
object you wish to use
<Bounds>
bounds
: bounds of the CRS in projected coordinates
<List<double>>
resolutions
: an array of zoom factors (projection units per pixel, eg. meters/pixel)
<List<double>>
scales
: scale factors (pixels per projection unit); specify either scales or resolutions, but not both!
<List<Point>>
origins
: tile origin in projected coordinates (for TileLayer). Why is it needed? GeoServer by default can define different origins (top left coordinates) for each zoom levels. In case of origin mismatch the tile will be drawn on the wrong place: the map will jump at such zoom levels. If your origins vary with zoom levels the number of origins must match the number of resolutions. You can get the desired origins from a GetCapabilities
WMTS call from geoserver e.g. http://[ip:port]/geoserver/gwc/service/wmts?request=GetCapabilities
. This results an XML, and you have to look up for the TopLeftCorner
s for each TileMatrix of your TileMatrixSet.
<Transformation>
transformation
: the transformation to use when transforming projected coordinates into pixel coordinates
An example:
Proj4Crs has multiple uses:
Set FlutterMap
's default CRS:
Set a WMS layer's CRS
For complete code (with point transformation from one projection to another) see the page source code. This is how it looks like:
The InteractionOptions
object passed to MapOptions.interactiveOptions
configures the gestures that the user can use to interact with the map. For example, disable rotation or configure cursor/keyboard rotation.
flags
is a bitfield that enables and disables the vast majority of gestures. Although technically the type is of int
, it is usually set with a combination of InteractiveFlag
s.
Note that some gestures must be configured by other means, either instead of using flags, or in addition to.
By default, all
gestures are enabled, but a non-interactive map can be created using none
(and other options in addition).
The recommended way to create an entirely non-interactive map is to wrap the FlutterMap
widget in an IgnorePointer
widget.
Otherwise, to set flags, there's two methods:
Add flags, with the bitwise 'OR' (|
) operator in-between
For example, InteractiveFlag.drag | InteractiveFlag.rotate
Remove flags from all
, using the &
and ~
operators in-between
For example, InteractiveFlag.all & ~InteractiveFlag.rotate
Cursor/keyboard rotation is designed for desktop platforms, and allows the cursor to be used to set the rotation of the map whilst a (customizable) keyboard key (by default, any of the 'Control' keys) is held down.
The CursorKeyboardRotationOptions
object passed to the property with the corresponding name configures this behaviour. The CursorKeyboardRotationOptions.disabled()
constructor can be used to disable cursor/keyboard rotation.
There's many customization options, see the API docs for more information:
This is advanced behaviour that affects how gestures 'win' in the gesture arena, and does not usually need changing.
To dictate & restrict what the map can and should do, regardless of its contents, it needs some guidance!
It provides options that can be categorized into three main parts:
Initial positioning Defines the location of the map when it is first loaded
Permanent rules Defines restrictions that last throughout the map's lifetime
Event handling Defines methods that are called on specific map events
Changing these properties after the map has already been built for the first time will have no effect: they only apply on initialisation.
To control the map programatically, use a MapController
: Controllers & Cameras.
One part of MapOptions
responsibilities is to define how the map should be positioned when first loaded. There's two ways to do this (that are incompatible):
initialCenter
(LatLng
) & initialZoom
initialCameraFit
by bounds (): CameraFit.bounds
by bounds (): CameraFit.insideBounds
by coordinates (): CameraFit.coordinates
It is possible to also set the map's initialRotation
in degrees, if you don't want it North (0°) facing initially.
If rotation is enabled/allowed, if using initialCameraFit
, prefer defining it by coordinates for a more intended/tight fit.
One part of MapOptions
responsibilities is to define the restrictions and limitations of the map and what users can/cannot do with it.
Some of the options are described elsewhere in this documentation, in context. In addition, the API docs show all the available options, and below is a partial list of options:
cameraConstraint
camera bounds inside bounds: CameraConstraint.bounds
camera center inside bounds: CameraConstraint.center
unconstrained (default): CameraConstraint.unconstrained
maxZoom
and minZoom
Sets a hard limit on the maximum and minimum amounts that the map can be zoomed
interactionOptions
Configures the gestures that the user can use to interact with the map - for example, disable rotation or configure cursor/keyboard rotation
Instead of maxZoom
(or in addition to), consider setting maxNativeZoom
per TileLayer
instead, to allow tiles to scale (and lose quality) on the final zoom level, instead of setting a hard limit.
FM does have some support for using alternative CRSs.