Displays DJI Geo Zones on an OpenLayers map. Also, you can add a Control Panel with map legends and selectors to change the drone and the levels to be shown.
The data is obtained directly from an undocumented DJI API. The official DJI Fly Safe Geo Zone Map that use the same data can be found here, and more information here.
Tested with OpenLayers version 5, 6, 7, 8 and 9.
Nowadays, DJI doesn't offer any API documentation, so future support and access to the data is uncertain. Furthermore, the API endpoint has CORS restrictions and the header Content-Security-Policy: frame-ancestors 'self' http://*.dji.com https://*.dji.com
, so all browsers requests must be proxied.
All the examples are configured using a free Proxy. If you notice some lag or slow performance, try one of your own.
- Basic usage: create an OpenLayers map instance, and pass that map and options to the DjiGeozones constructor.
// Default options
let opt_options = {
urlProxy: '',
buffer: 10000, // to increase search zone (in meters)
drone: 'spark', // See drone parameter in the DJI API section
zonesMode: 'total', // See drone parameter in the DJI API section
country: 'US', // See country parameter in the DJI API section
showGeozoneIcons: true, // Display geozones icons
displayLevels: [2, 6, 1, 0, 3, 4, 7], // Order is kept in the Control Panel
activeLevels: [2, 6, 1, 0, 3, 4, 7],
createPanel: 'full', // Create or not the control
targetPanel: null, // Specify a target if you want the control to be rendered outside of the map's viewport.
startCollapsed: false,
startActive: true,
dronesToDisplay: [], // By default, an array with all the drones
extent: null,
loadingElement:
'<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>',
clickEvent: 'singleclick',
language: 'en',
i18n: {}, // Create customized languages/texts. See i18n folder
alert: null
};
// SETTING A REVERSE PROXY TO AVOID CORS
// For testing, you can run `chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security` to
// launch a Google Chrome instance with CORS disabled.
// This example uses allOrigins (https://github.com/gnuns/allOrigins), a free and open source javascript proxy.
// For production, deploy a custom instance or use yor own proxy.
opt_options.urlProxy = 'https://api.allorigins.win/raw?url=';
const djiGeozones = new DjiGeozones(opt_options);
map.addControl(djiGeozones); // or djiGeozones.setMap(map)
// Instance methods
// This methods clean the loaded features and fires a new API request.
djiGeozones.drone = 'spark';
djiGeozones.country = 'US'; // At the moment, this doesn't seem to affect the api response
djiGeozones.zonesMode = 'total';
djiGeozones.activeLevels = [1, 2, 3, 4, 6, 7]; // Set custom level values
djiGeozones.addLevels(5);
djiGeozones.removeLevels(7);
djiGeozones.setPanelVisible(true); // Show/hide the control panel
djiGeozones.setPanelCollapsed(true); // Collapse/expand the control panel
djiGeozones.hide(); // Hide the GeoZones and the map Control
djiGeozones.show(); // Show the GeoZones and the map Control
let layers = djiGeozones.layers; // array of ol/layer/Vector~VectorLayer instances
let layer = djiGeozones.getLayerByLevel(7); // returns an ol/layer/Vector~VectorLayer instance with the specefic level
djiGeozones.once(`init`, () => console.log('Library is loaded'));
djiGeozones.on(`error`, () => console.log('An error ocurred'));
DJI API - What we know
-
The API doesn't accepts requests in large zoom levels (<9) aka search_radius, so the Geozones in the map are disabled in these zoom scales to manage this beahaivor.
-
The data returned by the API has some problems/strange behaviors:
- The elements in level 6 (Altitude Zones, grey color) are returning from the api with level 2 in the properties (Restricted Zones, red color), and the elements in level 4 (Regulatory Restricted Zones, light blue color) with level 7 (Recommended Zones, green color). This makes very messy the frontend, and make it impossible to filter these levels accordingly in each request. To avoid this problem, this module functions completely different from the official map: performs the API requests including all levels, distributing the results in differents layers according to each level, and filtering that manipulating the layers visibility (not by the API request).
-
See DjiApi API for parameters and details.
See CHANGELOG for details of changes in each release.
Load ol-dji-geozones.js
after OpenLayers. Dji Geozones is available as DjiGeozones
.
<script src="https://unpkg.com/ol-dji-geozones@2.3.0"></script>
<link rel="stylesheet" href="https://unpkg.com/ol-dji-geozones@2.3.0/dist/ol-dji-geozones.min.css" />
NPM package: ol-dji-geozones.
Install the package via npm
npm install ol-dji-geozones
import DjiGeozones from 'ol-dji-geozones';
// css
import 'ol-dji-geozones/lib/css/ol-dji-geozones.css';
// or scss
import 'ol-dji-geozones/lib/scss/ol-dji-geozones.scss';
TypeScript types are shipped with the project in the dist directory and should be automatically used in a TypeScript project. Interfaces are provided for DjiGeozones Options.
- DjiGeozones
- ErrorEvent
- deepObjectAssign
- ApiReqArguments
- i18n
- Options
Extends ol/control/Control~Control
OpenLayers Dji Geozones, creates multiples VectorLayers to display interactives DJI Geo Zones on the map, requesting the data on the fly to an DJI API.
Also, add a Control to select levels of interest and drone to filter the results.
opt_options
Options? DjiGeozones options, see DjiGeozones Options for more details.
Remove the control from its current map and attach it to the new map. Pass null to just remove the control from the current map.
map
Map
Returns void
Show or hides the control panel
visible
boolean
Returns void
Collapse/expand the control panel
collapsed
boolean
Returns void
Get all the layers
Type: Array<VectorLayer<Feature>>
Returns Array<VectorLayer<Feature>>
Get the layer acordding the level
level
number
Returns VectorLayer<Feature>
Setter for API parameter drone
. Triggers an API request
Type: string
drone
string
Getter for Api parameter drone
Type: string
Returns string
Setter for API parameter zonesMode
. Triggers an API request
Type: string
zonesMode
string
Getter for API parameter zonesMode
Type: string
Returns string
Setter for API parameter country
. Triggers an API request
Type: string
country
string
Getter for API parameter country
Type: string
Returns string
Get all the parameters from a level and the i18n texts
id
number (optional, defaultnull
)
Returns Level
Replace the active levels with this values and refresh the view
Add the level/s to the view
levels
(Array<number> | number)refresh
If true, refresh the view and show the active levels (optional, defaulttrue
)
Returns void
Remove the level/s from the view
levels
(Array<number> | number)refresh
If true, refresh the view and show the actived levels (optional, defaulttrue
)
Returns void
Removes the control, layers, overlays and events from the map
Returns void
Hide the geoZones and the Control
Returns void
Show the geoZones and the Control
Returns void
Extends BaseEvent
Custom Event to pass error in the dispatchEvent
error
Error
target
sources
...any
[interface] - Dji Api Parameters for requests
0
- Warning Zones1
- Authorization Zones2
- Restricted Zones3
- Enhanced Warning Zones4
- Regulatory Restricted Zones5
- Recommended Zones (2) Apparently this level is only valid for Japan6
- Altitude Zones7
- Recommended Zones8
- Approved Zones for Light UAVs(China) Only valid for China9
- Densely Populated Area NOT SUPPORTED - This level exists in the oficial Geo Zone Map, but this data is not provided by the api. On the other hand, now days this level is apparently valid only for Japan and China
dji-mavic-3
(Mavic 3)dji-mini-se
(Mavic Mini SE)dji-air-2s
(Air 2s)dji-fpv
(FPV)mavic-mini-2
(Mavic Mini 2)mavic-mini
(Mavic Mini)mavic-2-enterprise
(Mavic 2 Enterprise)mavic-2
(Mavic 2)mavic-air
(Mavic Air)mavic-air-2
(Mavic Air 2)mavic-pro
(Mavic Pro)spark
(Spark)phantom-4-pro
(Phantom 4 Pro)phantom-4-advanced
(Phantom 4 Advanced)phantom-4
(Phantom 4)phantom-4-rtk
(Phantom 4 RTK)phantom-4-multispectral
(Phantom 4 Multispectral)phantom-3-pro
(Phantom 3 Prophantom-3-advanced
(Phantom 3 Advanced)phantom-3-standard
(Phantom 3 Standard)phantom-3-4K
(Phantom 3 4K)phantom-3-se
(Phantom 3 SE)inspire-2
(Inspire 2)inspire-1-series
(Inspire 1 Series)m200-series
(M200 Series)m300-series
(M300 Series)m600-series
(M600 Series)m100
(M100)mg1p
(MG 1S/1A/1P/1P RTK/T10/T16/T20/T30)dji-mini-2
(DJI Mini 2)
Type: string
Apparently doesn't affects the response of the api
US
AR
- etc (See the supported list)
Type: string
Apparently only accepts 'total'
Type: string
Map View center point Longitude
Type: number
Map View center point Latitude
Type: number
Radius of the current view of the map
Type: number
[interface] - Custom Language specified when creating a DjiGeozones
[interface] - DjiGeozones Options specified when creating a DjiGeozones instance
Default values:
{
urlProxy: '',
encodeURIRequest: true,
buffer: 10000, // meters
drone: 'spark', // See parameter in the DJI API section
zonesMode: 'total', // See parameter in the DJI API section
country: 'US', // See parameter in the DJI API section
showGeozoneIcons: true, // Display geozones icons
displayLevels: [2, 6, 1, 0, 3, 4, 7],
activeLevels: [2, 6, 1, 0, 3, 4, 7],
createPanel: 'full',
targetPanel: null,
startCollapsed: true,
startActive: true,
dronesToDisplay: null,
extent: null,
loadingElement: '<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>',
clickEvent: 'singleclick',
theme: 'light',
language: 'en',
i18n: {...} // Translations according to selected language
alert: alert // Default browser alert function
}
Url/endpoint from a Reverse Proxy to avoid CORS restrictions
Type: string
To encode or not the outgoing request (depending on proxy)
Type: boolean
Current map radius is increased by the provided value (in meters) and used to request the areas. Very useful for the highest zoom levels, to allow geozones near by being displayed. A value of 0 will only search geozones (the centroid of these) that are inside the current view extent.
Type: number
zonesMode to be used in the API request
Type: string
Country identifier to be used in the API request
Type: string
Display geozones icons
Type: boolean
Geozone Levels to be shown in the control panel
Geozone Levels to be actived by default in the Control and API request
Use a custom drone list to show in the select. If not provided, we use all the available drones The models are extracted from https://flysafe-api.dji.com/dji/drones See drone for the complete list.
Type: Array<Drone>
The bounding extent for layer rendering. The layers will not be rendered outside of this extent.
Type: Extent
Create or not a control panel on the map
- 'full' displays each level as a layer, with the possibility to activate or deactivate each one, color legends and a drone switcher.
- 'compact' it's a simple toggler button to enable/disable the geoZones.
- use false to disable the panel
Type: (boolean | "full"
| "compact"
)
Specify a target if you want the control to be rendered outside of the map's viewport.
Type: (HTMLElement | string)
Whether panel is minimized when created.
Type: boolean
Show GeoZones on initialize
Type: boolean
Loading element to be shown in the Controller when loading API data
Type: string
Type of Click event to activate the PopUp
Type: ("singleclick"
| "dblclick"
)
Color theme of the Control Panel
Type: ("light"
| "dark"
)
Language to be used in the Controller panel and PopUp. This doesn't affects the API requests. If i18n is set, this will be ignored.
Type: ("en"
| "es"
)
Add custom translations
Type: i18n
Custom alert function to display messages
msg
string
Returns void
- Add test to check inexpected changes on the API response.
- Add customizable proxy function
- Improve scss (add variables)
- Add more events
MIT (c) Gastón Zalba.