Version 2 of this widget is not fully compatible with version 1.
- Removed
jsVarName
property. - Removed
scriptPosition
property. - Added JS module.
- Added
mapOptionScript
property. - Minor bug fixes.
This widget encapsulates the [OpenLayers 3] (http://openlayers.org/) library for easy use in Yii 2. It automatically registers the OpenLayers library and creates a map on the target div.
The widget also facilitates defining the complex configuration options for a map, featuring:
- Shortcut mechanisms to translate your PHP structures into JavaScript.
- Handling of extra JavaScript code to be applied to the map.
This is the preferred way of installing the widget. Just add sibilino/yii2-openlayers
to the composer.json
file of your Yii 2 application and perform a Composer Update as usual.
"require": {
"sibilino/yii2-openlayers": "*"
}
If for some reason you cannot or do not want to use Composer, then you must create the widget folder manually, and then configure your Yii 2 application to autoload the widget classes.
First, create the folder structure sibilino/yii2-openlayers/widget
inside the vendor
subfolder of your Yii 2 application.
Then, download the widget .zip file and extract the contents of its widget
subfolder into the folder you created in the previous step.
Next, edit your application's config file (usually config/main.php
or config/web.php
) and add the following alias:
[
//...
'aliases' => [
//...
'@sibilino/yii2/openlayers' => '@vendor/sibilino/yii2-openlayers/widget',
//...
],
//...
]
Remember to use the namespace sibilino\yii2\openlayers
when calling any of the widget's classes:
use sibilino\yii2\openlayers\OpenLayers;
use sibilino\yii2\openlayers\OL;
In your view, echo the widget method as usual. The options for the OpenLayers Map() can be specified in mapOptions
.
The widget will automatically publish the OpenLayers library and output the div that will receive the map.
The widget supports the following configuration options (actual OpenLayers.js options go in the mapOptions
array):
id
: The id for the widget and the generated container div.options
: Array of HTML options for the container div.mapOptions
: The configuration array to be passed to the JavaScript OpenLayers Map() constructor. Thetarget
option is handled automatically if not specified. Its structure and available options are the same that are supported by the [OpenLayers 3 library] (http://openlayers.org/). Some simplifications are supported, as described below.mapOptionScript
: Url of a JavaScript file to be registered after the olwidget.js module. Can be array, to register multiple scripts. Scripts can register options for a map with idmapId
by setting them insibilino.olwidget.mapOptions[mapId]
. See below for details.
The problem with OpenLayers map options is that they require complex JavaScript structures. Two approches are available:
- Managing your configuration in PHP and then translating it to JavaScript.
- Managing your configuration directly in JavaScript.
If your map configuration is relatively simple and depends mostly on data structures that already exist in your PHP application, approach #1 will probably be easier. This widget contains the OL class that can facilitate PHP to JavaScript translation. See below for details.
When your configuration begins getting complex, the OL class begins to show limitations and you must use JsExpressions, which are no longer easy to nest and basically mean you are again writing plain JavaScript. In this case, approach #2 is probably necessary. This widget provides a JavaScript module that easily passes your configuration from a script file to the created map. See below for details.
Mixing up both approaches can be the best way to easily define your map configuration.
The idea is to define the JavaScript options for OpenLayers as a PHP array, using new OL('something')
when the JavaScript requires new ol.something()
, and let the widget manage the translation to JavaScript automatically.
For example:
use sibilino\yii2\openlayers\OpenLayers;
use sibilino\yii2\openlayers\OL;
use yii\web\JsExpression;
//...
echo OpenLayers::widget([
'id' => 'test',
'mapOptions' => [
'layers' => [
// Easily generate JavaScript "new ol.layer.Tile()" using the OL class
new OL('layer.Tile', [
'source' => new OL('source.MapQuest', [
'layer' => 'sat',
]),
]),
],
// Using a shortcut, we can skip the OL('View' ...)
'view' => [
// Of course, the generated JS can be customized with JsExpression, as usual
'center' => new JsExpression('ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857")'),
'zoom' => 4,
],
],
]);?>
For configuration details, read the next section.
For details and examples on OpenLayers configuration, see [the official OpenLayers 3 documentation] (http://openlayers.org/).
Many of the OpenLayers options must be specified by an instance of a JavaScript object under the "ol" namespace. This would traditionally require a JsExpression with a string such as new ol.layer.Tile()
(for a Tile object), with further complications to pass configuration to the constructed object.
To avoid this cumbersome notation, the OL class can be used. Its constructor accepts a classname, which can include namespace information, and an array of options for the classname's constructor. For example:
$olObject = new OL('source.MapQuest', ['layer' => 'sat']);
Each OL object behaves as a JsExpression that will generate the JavasCript code to instantiate the specified classname with the options. In the case of the example, the resulting code would be:
new ol.source.MapQuest({layer:"sat"})
In the end, this allows the PHP configuration array to be created just like the desired JavaScript configuration object, but using new OL('Something')
whenever new ol.Something()
is required.
When specifying the mapOptions['view']
or mapOptions['layers']
arrays, you can identify the some objects by specifying them with a string, instead of creating the corresponding OL instance.
The options that support such a string shortcut are mapOptions['view']
and any layer in mapOptions['layers']
. For example:
'mapOptions' => [
'layers' => [
'Tile' => [ // The layer type as a string, no need for new OL('layer.Tile' ...)
'source' => new OL('source.MapQuest', [
'layer' => 'sat',
])
],
],
'view' => [ // The 'view' option does not require new OL('View' ...) either
'center' => new JsExpression('ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857")'),
'zoom' => 4,
],
],
In addition, whenever a layer has been defined using a type string, the source can also be specified using a type string. For example:
'mapOptions' => [
'layers' => [
// Again no need for OL('ol.source.OSM'), but no configuration can be passed to the OSM object in this case.
'Tile' => 'OSM',
],
],
The widget publishes a JavaScript module that is exposed in the global scope as sibilino.olwidget
. Options for the creation of the map with id mapId
can be specified as an object in the sibilino.olwidget.mapOptions
array, associated with the mapId
key. For example:
var select = new ol.interaction.Select({...});
sibilino.olwidget.mapOptions['mainMap'] = {
layers: [
new ol.layer.Vector({...})
],
interactions: ol.interaction.defaults().extend([select])
}
You can register this kind of script by setting its web-accessible URL in the mapOptionScript
property of the PHP widget. For example:
echo OpenLayers::widget([
'id' => 'mainMap',
'mapOptionScript' => '@web/js/yourscript.js',
'mapOptions' => [
// Put your PHP-generated options here.
// These options will be merged with the ones in yourscript.js.
// For example:
'layers' => [
'Tile' => [
'source' => new OL('source.MapQuest', [
'layer' => $selectedLayer,
]),
],
'Vector' => [
'source' => new OL('source.Cluster', [
'distance' => 30,
'source' => new OL('source.Vector', [
'features' => $features,
]),
]),
],
],
// ...
],
//...
]);
Alternatively, you can access the sibilino.olwidget
module from any JavaScript code that is loaded after the module script. To ensure proper script order, you can use a dependency to sibilino\yii2\openlayers\OLModuleBundle
. For example:
$view->registerJsFile($script, ['depends' => OLModuleBundle::className()]);
If you have JavaScript code that needs to work with the map object created by the widget in your PHP code, you can find it using sibilino.olwidget.getMapById(mapId)
. This function returns the map object created by the widget with the id mapId
. For example:
// Assuming the PHP widget was given the id "mainMap"
var map = sibilino.olwidget.getMapById("mainMap");