@syncfusion/ej2-maps
Version:
The Maps component is used to visualize the geographical data and represent the statistical data of a particular geographical area on earth with user interactivity, and provides various customizing options
454 lines (453 loc) • 27.8 kB
JavaScript
import { findMidPointOfPolygon, Rect, filter, getTemplateFunction, getZoomTranslate, getTranslate, RectOption, convertElementFromLabel, Point, TextOption, renderTextElement, textTrim, Internalize, measureTextElement } from '../utils/helper';
import { isNullOrUndefined, Animation, animationMode } from '@syncfusion/ej2-base';
import { dataLabelRendering } from '../model/constants';
/**
* DataLabel Module used to render the maps datalabel
*/
var DataLabel = /** @class */ (function () {
function DataLabel(maps) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.value = { rightWidth: 0, leftWidth: 0, heightTop: 0, heightBottom: 0 };
this.maps = maps;
this.dataLabelCollections = [];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
DataLabel.prototype.getDataLabel = function (dataSource, labelPath, shapeName, shapeDataPath) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var text;
var shapeNameValue;
for (var i = 0; i < (isNullOrUndefined(dataSource) ? 0 : dataSource.length); i++) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var data = dataSource[i];
var dataShapePathValue = !isNullOrUndefined(data[shapeDataPath]) && isNaN(data[shapeDataPath]) &&
typeof data[shapeDataPath] === 'string' ? data[shapeDataPath].toLowerCase() : data[shapeDataPath];
shapeName = !isNullOrUndefined(shapeName) && typeof shapeName === 'string' ? shapeName.toString() : shapeName;
shapeNameValue = !isNullOrUndefined(shapeName) && typeof shapeName === 'string' ? shapeName.toLowerCase() : shapeName;
if ((dataShapePathValue) === shapeNameValue) {
text = data;
break;
}
}
return text;
};
/**
* To render label for maps.
*
* @param {LayerSettings} layer - Specifies the layer settings
* @param {number} layerIndex - Specifies the layer index.
* @param {object} shape - Specifies the shape.
* @param {any[]} layerData - Specifies the layer data.
* @param {Element} group Specifies the element.
* @param {HTMLElement} labelTemplateElement - Specifies the template element.
* @param {number} index - Specifies the index number.
* @param {any[]} intersect - Specifies the intersect.
* @returns {void}
* @private
*/
DataLabel.prototype.renderLabel = function (layer, layerIndex, shape,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layerData, group, labelTemplateElement, index, intersect) {
var _this = this;
var dataLabel = layer.dataLabelSettings;
var style = layer.dataLabelSettings.textStyle;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var templateFn;
var options;
var dataLabelSettings = layer.dataLabelSettings;
var labelpath = layer.dataLabelSettings.labelPath;
var shapePoint = [[]];
var midIndex = 0;
var pointsLength = 0;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var shapeData = shape;
var element;
var rect;
var text = '';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var datasrcObj;
var currentLength = 0;
var oldIndex;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var location;
var sublayerIndexLabel = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var shapeProperties = shape['properties'];
var labelId = this.maps.element.id + '_LayerIndex_' + layerIndex + '_shapeIndex_' + index + '_LabelIndex_' + index;
var textLocation = new Point(0, 0);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var shapes = layerData[index];
var locationX;
var locationY;
style.fontFamily = this.maps.theme.toLowerCase() !== 'material' ? this.maps.themeStyle.labelFontFamily : style.fontFamily;
style.fontWeight = style.fontWeight || this.maps.themeStyle.fontWeight;
style.size = style.size || this.maps.themeStyle.fontSize;
shape = !isNullOrUndefined(shapes) ? shapes['property'] : null;
var properties = (Object.prototype.toString.call(layer.shapePropertyPath) === '[object Array]' ?
layer.shapePropertyPath : [layer.shapePropertyPath]);
var propertyPath;
var isPoint = false;
var animate = (layer.animationDuration !== 0 || animationMode === 'Enable') || isNullOrUndefined(this.maps.zoomModule);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var translate = (this.maps.isTileMap) ? new Object() : ((this.maps.zoomSettings.zoomFactor > 1 &&
!isNullOrUndefined(this.maps.zoomModule)) ? getZoomTranslate(this.maps, layer, animate) :
getTranslate(this.maps, layer, animate));
var scale = (this.maps.isTileMap) ? this.maps.scale : translate['scale'];
var transPoint = (this.maps.isTileMap) ? this.maps.translatePoint : translate['location'];
var zoomTransPoint = this.maps.zoomTranslatePoint;
var shapeWidth;
var scaleZoomValue = !isNullOrUndefined(this.maps.scale) ? Math.floor(this.maps.scale) : 1;
var zoomLabelsPosition = this.maps.zoomSettings.enable ? !isNullOrUndefined(this.maps.zoomShapeCollection) &&
this.maps.zoomShapeCollection.length > 0 && !this.maps.isAddLayer : this.maps.zoomSettings.enable;
this.maps.translateType = 'labels';
for (var j = 0; j < properties.length; j++) {
if (shapeProperties[properties[j]]) {
propertyPath = properties[j];
datasrcObj = this.getDataLabel(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.dataSource, layer.shapeDataPath, shapeData['properties'][propertyPath], layer.shapeDataPath);
if (datasrcObj) {
break;
}
}
}
datasrcObj = this.getDataLabel(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.dataSource, layer.shapeDataPath, shapeData['properties'][propertyPath], layer.shapeDataPath);
if (!isNullOrUndefined(shapes) && !isNullOrUndefined(shapes['property'])) {
shapePoint = [[]];
if (!layerData[index]['_isMultiPolygon'] && layerData[index]['type'] !== 'Point' && layerData[index]['type'] !== 'MultiPoint') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
shapePoint.push(this.getPoint(layerData[index], []));
currentLength = shapePoint[shapePoint.length - 1].length;
if (pointsLength < currentLength) {
pointsLength = currentLength;
midIndex = shapePoint.length - 1;
}
}
else if (layerData[index]['type'] !== 'Point' && layerData[index]['type'] !== 'MultiPoint') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var layer_1 = layerData[index];
for (var j = 0; j < layer_1.length; j++) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
shapePoint.push(this.getPoint(layer_1[j], []));
currentLength = shapePoint[shapePoint.length - 1].length;
if (pointsLength < currentLength) {
pointsLength = currentLength;
midIndex = shapePoint.length - 1;
}
}
}
}
text = (!isNullOrUndefined(datasrcObj)) ? !isNullOrUndefined(datasrcObj[labelpath]) ?
datasrcObj[labelpath].toString() : shapeData['properties'][labelpath] || datasrcObj[layer.shapeDataPath] : shapeData['properties'][labelpath];
if ((Object.prototype.toString.call(layer.shapePropertyPath) === '[object Array]') &&
(isNullOrUndefined(text) && (!isNullOrUndefined(layer.dataSource) && layer.dataSource['length'] === 0))) {
for (var l = 0; l < layer.shapePropertyPath.length; l++) {
if (shapeData['properties'][layer.shapePropertyPath[l]]) {
text = shapeData['properties'][layer.shapePropertyPath[l]];
break;
}
}
}
if (isNullOrUndefined(text) && (layer.dataLabelSettings.template !== '' && layer.dataSource['length'] === 0)) {
text = shapeData['properties'][layer.shapePropertyPath];
}
if (isNullOrUndefined(text) && (!isNullOrUndefined(layer.dataSource) && layer.dataSource['length'] > 0)) {
text = '';
}
var dataLabelText = text;
var projectionType = this.maps.projectionType;
if (isPoint) {
location = {
x: shapePoint[midIndex][index]['x'], y: shapePoint[midIndex][index]['y'],
rightMin: 0, rightMax: 0, leftMin: 0, leftMax: 0,
points: shapePoint[midIndex][index], topMax: 0, topMin: 0,
bottomMax: 0, bottomMin: 0, height: 0
};
}
else {
location = findMidPointOfPolygon(shapePoint[midIndex], projectionType, layer.geometryType);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var firstLevelMapLocation = location;
if (!isNullOrUndefined(text) && !isNullOrUndefined(location)) {
if (zoomLabelsPosition && scaleZoomValue > 1 && !this.maps.zoomNotApplied && dataLabel.template === '') {
if (layerIndex > 0) {
for (var k = 0; k < this.maps.zoomLabelPositions.length; k++) {
if (this.maps.zoomLabelPositions[k]['dataLabelText'] === text) {
oldIndex = index;
index = k;
sublayerIndexLabel = true;
break;
}
}
}
locationX = location['x'];
locationY = location['y'];
location['x'] = ((location['x'] + zoomTransPoint['x']) * scale);
location['y'] = ((location['y'] + zoomTransPoint['y']) * scale);
}
location['y'] = (this.maps.projectionType === 'Mercator') || layer.geometryType === 'Normal' ? location['y'] : (-location['y']);
if (!isNullOrUndefined(this.maps.format) && !isNaN(Number(text)) && !isNaN(parseFloat(text))) {
if (this.maps.useGroupingSeparator) {
text = Internalize(this.maps, parseFloat(text));
if (!isNullOrUndefined(datasrcObj)) {
datasrcObj[labelpath] = text;
}
}
}
var eventargs_1 = {
name: dataLabelRendering, maps: this.maps, cancel: false, border: { color: dataLabel.border.color,
width: dataLabel.border.width, opacity: dataLabel.border.opacity }, datalabel: dataLabel,
fill: dataLabel.fill, template: dataLabel.template, text: text, offsetX: 0, offsetY: 0
};
this.maps.trigger('dataLabelRendering', eventargs_1, function (labelArgs) {
if (eventargs_1.cancel) {
return;
}
var position = [];
var width = zoomLabelsPosition && scaleZoomValue > 1 && !_this.maps.zoomNotApplied
&& _this.maps.zoomShapeCollection.length > index ? (_this.maps.dataLabelShape[index]) * scale :
(location['rightMax']['x'] - location['leftMax']['x']) * scale;
if (!isNullOrUndefined(_this.maps.dataLabelShape) && !_this.maps.isReset) {
shapeWidth = firstLevelMapLocation['rightMax']['x'] - firstLevelMapLocation['leftMax']['x'];
_this.maps.dataLabelShape.push(shapeWidth);
}
if (eventargs_1.text !== text && !eventargs_1.cancel) {
text = eventargs_1.text;
}
var textSize = measureTextElement(text, style);
var trimmedLable = text;
var elementSize = textSize;
var startY = location['y'] - textSize['height'] / 2;
var endY = location['y'] + textSize['height'] / 2;
var start = ((location['y'] + transPoint['y']) * scale) - textSize['height'] / 2;
var end = ((location['y'] + transPoint['y']) * scale) + textSize['height'] / 2;
position = filter(shapePoint[midIndex], startY, endY);
if (!isPoint && position.length > 5 && (shapeData['geometry']['type'] !== 'MultiPolygon') &&
(shapeData['type'] !== 'MultiPolygon')) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var location1 = findMidPointOfPolygon(position, projectionType, layer.geometryType);
if (zoomLabelsPosition && scaleZoomValue > 1 && !_this.maps.zoomNotApplied && eventargs_1.template === '') {
location1['x'] = ((_this.maps.zoomLabelPositions[index]['location']['x'] + zoomTransPoint['x']) * scale);
location1['y'] = ((_this.maps.zoomLabelPositions[index]['location']['y'] + zoomTransPoint['y']) * scale);
}
locationX = location1['x'];
location['x'] = location1['x'];
width = zoomLabelsPosition && scaleZoomValue > 1 && !_this.maps.zoomNotApplied
&& _this.maps.zoomShapeCollection.length > index ? (_this.maps.dataLabelShape[index]) * scale :
((location1['rightMax']['x'] - location1['leftMax']['x']) * scale) > 0 ?
((location1['rightMax']['x'] - location1['leftMax']['x']) * scale) : width;
}
var xpositionEnds = ((location['x'] + transPoint['x']) * scale) + textSize['width'] / 2;
var xpositionStart = ((location['x'] + transPoint['x']) * scale) - textSize['width'] / 2;
_this.value[index] = { rightWidth: xpositionEnds, leftWidth: xpositionStart, heightTop: start, heightBottom: end };
var labelElement;
if (eventargs_1.template !== '') {
templateFn = getTemplateFunction(eventargs_1.template, _this.maps);
var templateElement = templateFn ? templateFn(!isNullOrUndefined(datasrcObj) ?
datasrcObj : shapeData['properties'], _this.maps, eventargs_1.template, _this.maps.element.id + '_LabelTemplate', false) : document.createElement('div');
templateElement.innerHTML = !templateFn ? eventargs_1.template : '';
labelElement = convertElementFromLabel(templateElement, labelId, !isNullOrUndefined(datasrcObj) ? datasrcObj : shapeData['properties']);
if (_this.maps.isTileMap) {
labelElement.style.left = (((location['x'] + transPoint['x']) * scale) - (textSize['width'] / 2)) + 'px';
labelElement.style.top = (((location['y'] + transPoint['y']) * scale) - textSize['height']) + 'px';
}
else {
labelElement.style.left = ((Math.abs(_this.maps.baseMapRectBounds['min']['x'] - location['x'])) * scale) + labelArgs.offsetX + 'px';
labelElement.style.top = ((Math.abs(_this.maps.baseMapRectBounds['min']['y'] - location['y'])) * scale) + labelArgs.offsetY + 'px';
}
labelTemplateElement.appendChild(labelElement);
}
else {
var smartLabelMode = !isNullOrUndefined(dataLabelSettings.smartLabelMode) ? dataLabelSettings.smartLabelMode.toString() : 'None';
if (smartLabelMode === 'Trim') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var textType = typeof text === 'number' ? text.toString() : text;
trimmedLable = textTrim(width, textType, style, null, true);
elementSize = measureTextElement(trimmedLable, style);
options = new TextOption(labelId, textLocation.x, textLocation.y, 'middle', trimmedLable, '', '');
}
if (smartLabelMode === 'None') {
options = new TextOption(labelId, (textLocation.x), textLocation.y, 'middle', text, '', '');
}
if (smartLabelMode === 'Hide') {
text = (width >= textSize['width']) ? text : '';
options = new TextOption(labelId, (textLocation.x), (textLocation.y), 'middle', text, '', '');
}
if (!isNullOrUndefined(options)) {
text = options['text'];
}
var intersectionAction = !isNullOrUndefined(dataLabelSettings.intersectionAction) ? dataLabelSettings.intersectionAction.toString() : 'None';
if (intersectionAction === 'Hide') {
for (var i = 0; i < intersect.length; i++) {
if (!isNullOrUndefined(intersect[i])) {
if (!(_this.value[index]['leftWidth'] > intersect[i]['rightWidth']
|| _this.value[index]['rightWidth'] < intersect[i]['leftWidth']
|| _this.value[index]['heightTop'] > intersect[i]['heightBottom']
|| _this.value[index]['heightBottom'] < intersect[i]['heightTop'])) {
text = '';
break;
}
}
}
intersect.push(_this.value[index]);
options = new TextOption(labelId, textLocation.x, textLocation.y, 'middle', text, '', '');
}
var difference = void 0;
if (intersectionAction === 'Trim') {
for (var j = 0; j < intersect.length; j++) {
if (!isNullOrUndefined(intersect[j])) {
if (intersect[j]['rightWidth'] < _this.value[index]['leftWidth']
|| intersect[j]['leftWidth'] > _this.value[index]['rightWidth']
|| intersect[j]['heightBottom'] < _this.value[index]['heightTop']
|| intersect[j]['heightTop'] > _this.value[index]['heightBottom']) {
trimmedLable = text;
difference = 0;
}
else {
if (_this.value[index]['leftWidth'] > intersect[j]['leftWidth']) {
width = intersect[j]['rightWidth'] - _this.value[index]['leftWidth'];
difference = width - (_this.value[index]['rightWidth'] - _this.value[index]['leftWidth']);
trimmedLable = textTrim(difference, text, style, null, true);
break;
}
if (_this.value[index]['leftWidth'] < intersect[j]['leftWidth']) {
width = _this.value[index]['rightWidth'] - intersect[j]['leftWidth'];
difference = Math.abs(width - (_this.value[index]['rightWidth'] - _this.value[index]['leftWidth']));
trimmedLable = textTrim(difference, text, style, null, true);
break;
}
}
}
}
elementSize = measureTextElement(trimmedLable, style);
intersect.push(_this.value[index]);
options = new TextOption(labelId, textLocation.x, (textLocation.y), 'middle', trimmedLable, '', '');
}
if (intersectionAction === 'None') {
options = new TextOption(labelId, (textLocation.x), (textLocation.y), 'middle', text, '', '');
}
if (trimmedLable.length > 1) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var border = eventargs_1.border;
if (border['width'] > 1) {
var fill = eventargs_1.fill;
var opacity = dataLabelSettings.opacity;
var rx = dataLabelSettings.rx;
var ry = dataLabelSettings.ry;
var x = void 0;
var y = void 0;
var padding = 5;
if (zoomLabelsPosition && scaleZoomValue > 1 && !_this.maps.zoomNotApplied) {
x = ((location['x'])) - textSize['width'] / 2;
y = ((location['y'])) - textSize['height'] / 2 - padding;
}
else {
x = ((location['x'] + transPoint['x']) * scale) - textSize['width'] / 2;
y = ((location['y'] + transPoint['y']) * scale) - textSize['height'] / 2;
}
border.opacity = isNullOrUndefined(border.opacity) ? opacity : border.opacity;
var rectOptions = new RectOption(_this.maps.element.id + '_LayerIndex_' + layerIndex + '_shapeIndex_' + index + '_rectIndex_' + index, fill, border, opacity, new Rect((x + labelArgs.offsetX), (y + labelArgs.offsetY), textSize['width'], textSize['height']), rx, ry);
rect = _this.maps.renderer.drawRectangle(rectOptions);
rect.setAttribute('visibility', layer.dataLabelSettings.animationDuration > 0 || animationMode === 'Enable' ? 'hidden' : 'visibile');
group.appendChild(rect);
}
}
element = renderTextElement(options, style, style.color || _this.maps.themeStyle.dataLabelFontColor, group);
element.setAttribute('aria-label', text);
element.setAttribute('role', 'region');
element.setAttribute('visibility', layer.dataLabelSettings.animationDuration > 0 || animationMode === 'Enable' ? 'hidden' : 'visibile');
if (zoomLabelsPosition && scaleZoomValue > 1 && !_this.maps.zoomNotApplied) {
element.setAttribute('transform', 'translate( ' + ((location['x'] + labelArgs.offsetX)) + ' '
+ (((location['y'] + labelArgs.offsetY))) + ' )');
location['x'] = locationX;
location['y'] = locationY;
}
else {
element.setAttribute('transform', 'translate( ' + (((location['x'] + transPoint.x) * scale) + labelArgs.offsetX) + ' '
+ ((((location['y'] + transPoint.y) * scale) + (elementSize.height / 2)) + labelArgs.offsetY) + ' )');
}
group.appendChild(element);
}
_this.dataLabelCollections.push({
location: { x: location['x'] + labelArgs.offsetX, y: location['y'] + labelArgs.offsetY },
element: isNullOrUndefined(labelElement) ? element : labelElement,
layerIndex: layerIndex,
shapeIndex: sublayerIndexLabel ? oldIndex : index,
labelIndex: sublayerIndexLabel ? oldIndex : index,
dataLabelText: dataLabelText
});
if (labelTemplateElement.childElementCount > 0 && !_this.maps.element.contains(labelTemplateElement)) {
document.getElementById(_this.maps.element.id + '_Secondary_Element').appendChild(labelTemplateElement);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_this.maps.renderReactTemplates();
}
if (layer.dataLabelSettings.animationDuration > 0 || animationMode === 'Enable') {
if (!isNullOrUndefined(element)) {
_this.datalabelAnimate(element, dataLabelSettings.animationDuration, style.opacity, false);
if (!isNullOrUndefined(rect)) {
_this.datalabelAnimate(rect, dataLabelSettings.animationDuration, dataLabelSettings.opacity, true);
}
}
}
});
}
};
DataLabel.prototype.datalabelAnimate = function (element, duration, opacity, isRect) {
var height = 0;
new Animation({}).animate(element, {
duration: (duration === 0 && animationMode === 'Enable') ? 1000 : duration,
delay: 0,
progress: function (args) {
if (args.timeStamp > args.delay) {
height = ((args.timeStamp - args.delay) / args.duration);
element.setAttribute('style', 'user-select: none; visibility: visible;');
element.setAttribute(isRect ? 'fill-opacity' : 'opacity', (opacity * height).toString());
}
},
end: function () {
element.style.visibility = 'visible';
element.setAttribute(isRect ? 'fill-opacity' : 'opacity', opacity.toString());
}
});
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
DataLabel.prototype.getPoint = function (shapes, points) {
if (shapes['type'] === 'MultiLineString') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Array.prototype.forEach.call(shapes, function (current) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Array.prototype.forEach.call(current, function (shape) {
points.push(new Point(shape['point']['x'], shape['point']['y']));
});
});
}
else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Array.prototype.forEach.call(shapes, function (current) {
points.push(new Point(current['point']['x'], current['point']['y']));
});
}
return points;
};
/**
* Get module name.
*
* @returns {string} - Returns the module name.
*/
DataLabel.prototype.getModuleName = function () {
return 'DataLabel';
};
/**
* @returns {void}
* @private
*/
DataLabel.prototype.destroy = function () {
this.dataLabelCollections = [];
this.value = null;
this.maps = null;
};
return DataLabel;
}());
export { DataLabel };