@amcharts/amcharts4
Version:
amCharts 4
694 lines • 22.4 kB
JavaScript
/**
* Map series module
*/
import { __extends } from "tslib";
/**
* ============================================================================
* IMPORTS
* ============================================================================
* @hidden
*/
import { Series, SeriesDataItem } from "../series/Series";
import { registry } from "../../core/Registry";
import * as $type from "../../core/utils/Type";
import * as $math from "../../core/utils/Math";
import * as d3geo from "d3-geo";
/**
* ============================================================================
* DATA ITEM
* ============================================================================
* @hidden
*/
/**
* Defines a [[DataItem]] for [[MapSeries]].
*
* @see {@link DataItem}
*/
var MapSeriesDataItem = /** @class */ (function (_super) {
__extends(MapSeriesDataItem, _super);
/**
* Constructor
*/
function MapSeriesDataItem() {
var _this = _super.call(this) || this;
_this.className = "MapSeriesDataItem";
_this.values.value = {};
_this.applyTheme();
return _this;
}
Object.defineProperty(MapSeriesDataItem.prototype, "value", {
/**
* @return Value
*/
get: function () {
return this.values.value.value;
},
/**
* Numeric value of the data item.
*
* Value may be used in heat-map calculations.
*
* @param value Value
*/
set: function (value) {
this.setValue("value", value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "zoomLevel", {
/**
* @return Zoom level
*/
get: function () {
return this.properties["zoomLevel"];
},
/**
* When `zoomToMapObject()` is called the map will either calculate suitable
* zoom level itself or use object's `zoomLevel` if set.
*
* @param value Zoom level
*/
set: function (value) {
this.setProperty("zoomLevel", value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "zoomGeoPoint", {
/**
* @return Zoom geo point
*/
get: function () {
return this.properties["zoomGeoPoint"];
},
/**
* When `zoomToMapObject()` is called the map will either calculate suitable
* center position itself or use object's `zoomGeoPoint` if set.
*
* @param value Zoom geo point
*/
set: function (value) {
this.setProperty("zoomGeoPoint", value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "east", {
/**
* Longitude of the East-most point of the element.
*/
get: function () {
return this._east;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "west", {
/**
* Longitude of the West-most point of the element.
*/
get: function () {
return this._west;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "south", {
/**
* Latitude of the South-most point of the element.
*/
get: function () {
return this._south;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeriesDataItem.prototype, "north", {
/**
* Latitude of the North-most point of the element.
*/
get: function () {
return this._north;
},
enumerable: true,
configurable: true
});
/**
* Updates the item's bounding coordinates: coordinates of the East, West,
* North, and South-most points.
*
* @ignore Exclude from docs
*/
MapSeriesDataItem.prototype.updateExtremes = function () {
var geometry = this.getFeature().geometry;
if (geometry) {
var bounds = d3geo.geoBounds(geometry);
var west = bounds[0][0];
var south = bounds[0][1];
var north = bounds[1][1];
var east = bounds[1][0];
var changed = false;
if (north != this.north) {
this._north = $math.round(north, 6);
changed = true;
}
if (south != this.south) {
this._south = $math.round(south, 6);
changed = true;
}
if (east != this.east) {
this._east = $math.round(east, 6);
changed = true;
}
if (west != this.west) {
this._west = $math.round(west, 6);
changed = true;
}
// solves single russia prob
if (this._east < this._west) {
this._east = 180;
this._west = -180;
}
if (changed) {
this.component.invalidateDataItems();
}
}
};
MapSeriesDataItem.prototype.getFeature = function () {
return {};
};
return MapSeriesDataItem;
}(SeriesDataItem));
export { MapSeriesDataItem };
/**
* ============================================================================
* MAIN CLASS
* ============================================================================
* @hidden
*/
/**
* A base class for series of map objects.
*
* @see {@link IMapSeriesEvents} for a list of available Events
* @see {@link IMapSeriesAdapters} for a list of available Adapters
* @important
*/
var MapSeries = /** @class */ (function (_super) {
__extends(MapSeries, _super);
/**
* Constructor
*/
function MapSeries() {
var _this =
// Init
_super.call(this) || this;
_this.className = "MapSeries";
// Set defaults
_this.isMeasured = false;
_this.nonScalingStroke = true;
// Set data fields
_this.dataFields.value = "value";
_this.ignoreBounds = false;
if (_this.tooltip) {
_this.tooltip.showInViewport = true;
}
// Apply theme
_this.applyTheme();
return _this;
}
/**
* Returns a new/empty DataItem of the type appropriate for this object.
*
* @see {@link DataItem}
* @return Data Item
*/
MapSeries.prototype.createDataItem = function () {
return new MapSeriesDataItem();
};
/**
* Checks whether object should be included in series.
*
* @param includes A list of explicitly included ids
* @param excludes A list of explicitly excluded ids
* @param id Id of the object
* @return Include?
*/
MapSeries.prototype.checkInclude = function (includes, excludes, id) {
if (includes) {
if (includes.length == 0) {
return false;
}
else {
if (includes.indexOf(id) == -1) {
return false;
}
}
}
if (excludes && excludes.length > 0) {
if (excludes.indexOf(id) != -1) {
return false;
}
}
return true;
};
Object.defineProperty(MapSeries.prototype, "useGeodata", {
/**
* @return Use GeoJSON data?
*/
get: function () {
return this.getPropertyValue("useGeodata");
},
/**
* Should the map extract all the data about element from the GeoJSON?
*
* This is especially relevant for [[MapPolygonSeries]]. If not set to `true`
* polygon series will need to contain geographical data in itself in order
* to be drawn.
*
* If this is set to `true`, series will try to extract data for its objects
* from either chart-level `geodata` or from series' `geodata` which holds
* map infor in GeoJSON format.
*
* @default false
* @param value Use GeoJSON data?
*/
set: function (value) {
if (this.setPropertyValue("useGeodata", value)) {
this.invalidateData();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "include", {
/**
* @return Included objects
*/
get: function () {
return this.getPropertyValue("include");
},
/**
* A list of object ids that should be explictly included in the series.
*
* If this is not set, the series will automatically include all of the
* objects, available in the GeoJSON map. (minus the ones listed in
* `exclude`)
*
* If you need to display only specific objects, use `include`. E.g.:
*
* `include = ["FR", "ES", "DE"];`
*
* The above will show only France, Spain, and Germany out of the whole map.
*
* @param value Included objects
*/
set: function (value) {
if (this.setPropertyValue("include", value)) {
this.processIncExc();
}
},
enumerable: true,
configurable: true
});
/**
* @ignore
*/
MapSeries.prototype.processIncExc = function () {
//this.data = [];
this.invalidateData();
};
Object.defineProperty(MapSeries.prototype, "ignoreBounds", {
/**
* @return Ignore bounds?
*/
get: function () {
return this.getPropertyValue("ignoreBounds");
},
/**
* Should this series be included when calculating bounds of the map?
*
* This affects initial zoom as well as limits for zoom/pan.
*
* By default, `MapPolygonSeries` included (true), while `MapImageSeries` and
* `MapLineSeries` are not (`false`).
*
* @since 4.3.0
* @param value Ignore bounds?
*/
set: function (value) {
if (this.setPropertyValue("ignoreBounds", value)) {
if (this.chart) {
this.chart.updateExtremes();
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "exclude", {
/**
* @return Excluded ids
*/
get: function () {
return this.getPropertyValue("exclude");
},
/**
* A list of object ids that should be excluded from the series.
*
* E.g. you want to include all of the areas from a GeoJSON map, except
* Antarctica.
*
* You'd leave `include` empty, and set `exclude = ["AQ"]`.
*
* @param value Excluded ids
*/
set: function (value) {
if (this.setPropertyValue("exclude", value)) {
this.processIncExc();
}
},
enumerable: true,
configurable: true
});
/**
* Decorates a newly added object.
*
* @param event [description]
*/
MapSeries.prototype.handleObjectAdded = function (event) {
var mapObject = event.newValue;
mapObject.parent = this;
mapObject.series = this;
mapObject.strokeWidth = mapObject.strokeWidth;
};
Object.defineProperty(MapSeries.prototype, "geodata", {
/**
* @return GeoJSON data
*/
get: function () {
return this._geodata;
},
/**
* Map data in GeoJSON format.
*
* The series supports the following GeoJSON objects: `Point`, `LineString`,
* `Polygon`, `MultiPoint`, `MultiLineString`, and `MultiPolygon`.
*
* @see {@link http://geojson.org/} Official GeoJSON format specification
* @param geoJSON GeoJSON data
*/
set: function (geodata) {
if (geodata != this._geodata) {
this._geodata = geodata;
if (this.reverseGeodata) {
this.chart.processReverseGeodata(this._geodata);
}
for (var i = this.data.length - 1; i >= 0; i--) {
if (this.data[i].madeFromGeoData == true) {
this.data.splice(i, 1);
}
}
this.disposeData();
this.invalidateData();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "reverseGeodata", {
/**
* @returns Reverse the order of geodata coordinates?
*/
get: function () {
return this.getPropertyValue("reverseGeodata");
},
/**
* Indicates whether GeoJSON geodata supplied to the chart uses
* ESRI (clockwise) or non-ESRI (counter-clockwise) order of the polygon
* coordinates.
*
* `MapChart` supports only ESRI standard, so if your custom maps appears
* garbled, try setting `reverseGeodata = true`.
*
* @default false
* @since 4.10.11
* @param value Reverse the order of geodata coordinates?
*/
set: function (value) {
if (this.setPropertyValue("reverseGeodata", value) && this._geodata) {
this.chart.processReverseGeodata(this._geodata);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "geodataSource", {
/**
* Returns a [[DataSource]] specifically for loading Component's data.
*
* @return Data source
*/
get: function () {
if (!this._dataSources["geodata"]) {
this.getDataSource("geodata");
}
return this._dataSources["geodata"];
},
/**
* Sets a [[DataSource]] to be used for loading Component's data.
*
* @param value Data source
*/
set: function (value) {
var _this = this;
if (this._dataSources["geodata"]) {
this.removeDispose(this._dataSources["geodata"]);
}
this._dataSources["geodata"] = value;
this._dataSources["geodata"].component = this;
this.events.on("inited", function () {
_this.loadData("geodata");
}, undefined, false);
this.setDataSourceEvents(value, "geodata");
},
enumerable: true,
configurable: true
});
/**
* @ignore
*/
MapSeries.prototype.getFeatures = function () {
return;
};
/**
* @ignore
*/
MapSeries.prototype.validateDataItems = function () {
_super.prototype.validateDataItems.call(this);
this.updateExtremes();
};
/**
* @ignore
*/
MapSeries.prototype.updateExtremes = function () {
var north;
var south;
var east;
var west;
this.dataItems.each(function (dataItem) {
if (dataItem.north > north || !$type.isNumber(north)) {
north = dataItem.north;
}
if (dataItem.south < south || !$type.isNumber(south)) {
south = dataItem.south;
}
if (dataItem.west < west || !$type.isNumber(west)) {
west = dataItem.west;
}
if (dataItem.east > east || !$type.isNumber(east)) {
east = dataItem.east;
}
});
if (this._mapObjects) {
this._mapObjects.each(function (mapObject) {
if (mapObject.north > north || !$type.isNumber(north)) {
north = mapObject.north;
}
if (mapObject.south < south || !$type.isNumber(south)) {
south = mapObject.south;
}
if (mapObject.west < west || !$type.isNumber(west)) {
west = mapObject.west;
}
if (mapObject.east > east || !$type.isNumber(east)) {
east = mapObject.east;
}
});
}
if (this.north != north || this.east != east || this.south != south || this.west != west) {
this._north = north;
this._east = east;
this._west = west;
this._south = south;
this.dispatch("geoBoundsChanged");
if (!this.ignoreBounds) {
this.chart.updateExtremes();
}
}
};
Object.defineProperty(MapSeries.prototype, "north", {
/**
* @return Latitude
*/
get: function () {
if ($type.isNumber(this._northDefined)) {
return this._northDefined;
}
return this._north;
},
/**
* North-most latitude of the series.
*
* By default, this holds auto-calculated latitude of the extremity.
*
* It can be overridden manually.
*
* @param value Latitude
*/
set: function (value) {
this._northDefined = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "south", {
/**
* @return Latitude
*/
get: function () {
if ($type.isNumber(this._southDefined)) {
return this._southDefined;
}
return this._south;
},
/**
* South-most latitude of the series.
*
* By default, this holds auto-calculated latitude of the extremity.
*
* It can be overridden manually.
*
* @param value Latitude
*/
set: function (value) {
this._southDefined = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "west", {
/**
* @return Longitude
*/
get: function () {
if ($type.isNumber(this._westDefined)) {
return this._westDefined;
}
return this._west;
},
/**
* West-most longitude of the series.
*
* By default, this holds auto-calculated longitude of the extremity.
*
* It can be overridden manually.
*
* @param value Longitude
*/
set: function (value) {
this._westDefined = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MapSeries.prototype, "east", {
/**
* @return Longitude
*/
get: function () {
if ($type.isNumber(this._eastDefined)) {
return this._eastDefined;
}
return this._east;
},
/**
* East-most longitude of the series.
*
* By default, this holds auto-calculated longitude of the extremity.
*
* It can be overridden manually.
*
* @param value Longitude
*/
set: function (value) {
this._eastDefined = value;
},
enumerable: true,
configurable: true
});
/**
* Processes JSON-based config before it is applied to the object.
*
* @ignore Exclude from docs
* @param config Config
*/
MapSeries.prototype.processConfig = function (config) {
if ($type.hasValue(config["geodata"]) && $type.isString(config["geodata"])) {
var name_1 = config["geodata"];
// Check if there's a map loaded by such name
if ($type.hasValue(window["am4geodata_" + config["geodata"]])) {
config["geodata"] = window["am4geodata_" + config["geodata"]];
}
// Nope. Let's try maybe we got JSON as string?
else {
try {
config["geodata"] = JSON.parse(config["geodata"]);
}
catch (e) {
// No go again. Error out.
throw Error("MapChart error: Geodata `" + name_1 + "` is not loaded or is incorrect.");
}
}
}
_super.prototype.processConfig.call(this, config);
};
/**
* Adds `projection` to "as is" fields.
*
* @param field Field name
* @return Assign as is?
*/
MapSeries.prototype.asIs = function (field) {
return field == "geodata" || _super.prototype.asIs.call(this, field);
};
/**
* @ignore
*/
MapSeries.prototype.updateTooltipBounds = function () {
if (this.tooltip && this.topParent) {
this.tooltip.setBounds({ x: 10, y: 10, width: this.topParent.maxWidth - 20, height: this.topParent.maxHeight - 20 });
}
};
return MapSeries;
}(Series));
export { MapSeries };
/**
* Register class in system, so that it can be instantiated using its name from
* anywhere.
*
* @ignore
*/
registry.registeredClasses["MapSeries"] = MapSeries;
registry.registeredClasses["MapSeriesDataItem"] = MapSeriesDataItem;
//# sourceMappingURL=MapSeries.js.map