[3.0] Improvment image map (#2729)

* Add support setting position function

* Improved setting image map

* Add support setting offset marker
This commit is contained in:
Vladyslav 2020-05-05 13:47:37 +03:00 committed by GitHub
parent f7efb79015
commit adc982923d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 202 deletions

View File

@ -94,6 +94,8 @@ export type MarkerSettings = {
tooltipFunction: GenericFunction; tooltipFunction: GenericFunction;
labelFunction: GenericFunction; labelFunction: GenericFunction;
markerImageFunction?: MarkerImageFunction; markerImageFunction?: MarkerImageFunction;
markerOffsetX: number;
markerOffsetY: number;
} }
export interface FormattedData { export interface FormattedData {

View File

@ -96,7 +96,7 @@ export class MapWidgetController implements MapWidgetInterface {
const schema = initSchema(); const schema = initSchema();
addToSchema(schema, this.getProvidersSchema(mapProvider)); addToSchema(schema, this.getProvidersSchema(mapProvider));
addGroupInfo(schema, 'Map Provider Settings'); addGroupInfo(schema, 'Map Provider Settings');
addToSchema(schema, addCondition(commonMapSettingsSchema, 'model.provider !== "image-map"')); addToSchema(schema, commonMapSettingsSchema);
addGroupInfo(schema, 'Common Map Settings'); addGroupInfo(schema, 'Common Map Settings');
addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon'])); addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon']));
addGroupInfo(schema, 'Polygon Settings'); addGroupInfo(schema, 'Polygon Settings');

View File

@ -18,10 +18,12 @@ import L, { LeafletMouseEvent } from 'leaflet';
import { FormattedData, MarkerSettings } from './map-models'; import { FormattedData, MarkerSettings } from './map-models';
import { aspectCache, createTooltip, parseWithTranslation, safeExecute } from './maps-utils'; import { aspectCache, createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { isDefined } from '@core/utils';
export class Marker { export class Marker {
leafletMarker: L.Marker; leafletMarker: L.Marker;
tooltipOffset: [number, number]; tooltipOffset: [number, number];
markerOffset: [number, number];
tooltip: L.Popup; tooltip: L.Popup;
location: L.LatLngExpression; location: L.LatLngExpression;
data: FormattedData; data: FormattedData;
@ -34,9 +36,14 @@ export class Marker {
draggable: settings.draggableMarker draggable: settings.draggableMarker
}); });
this.markerOffset = [
isDefined(settings.markerOffsetX) ? settings.markerOffsetX : 0.5,
isDefined(settings.markerOffsetY) ? settings.markerOffsetY : 1,
];
this.createMarkerIcon((iconInfo) => { this.createMarkerIcon((iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
this.tooltipOffset = [0, -iconInfo.size[1] + 10]; this.tooltipOffset = [0, -iconInfo.size[1] * this.markerOffset[1] + 10];
this.updateMarkerLabel(settings); this.updateMarkerLabel(settings);
}); });
@ -95,7 +102,7 @@ export class Marker {
updateMarkerIcon(settings: MarkerSettings) { updateMarkerIcon(settings: MarkerSettings) {
this.createMarkerIcon((iconInfo) => { this.createMarkerIcon((iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
this.tooltipOffset = [0, -iconInfo.size[1] + 10]; this.tooltipOffset = [0, -iconInfo.size[1] * this.markerOffset[1] + 10];
this.updateMarkerLabel(settings); this.updateMarkerLabel(settings);
}); });
} }
@ -130,7 +137,7 @@ export class Marker {
const icon = L.icon({ const icon = L.icon({
iconUrl: currentImage.url, iconUrl: currentImage.url,
iconSize: [width, height], iconSize: [width, height],
iconAnchor: [width / 2, height], iconAnchor: [width * this.markerOffset[0], height * this.markerOffset[1]],
popupAnchor: [0, -height] popupAnchor: [0, -height]
}); });
const iconInfo = { const iconInfo = {
@ -152,7 +159,7 @@ export class Marker {
const icon = L.icon({ const icon = L.icon({
iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color, iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color,
iconSize: [21, 34], iconSize: [21, 34],
iconAnchor: [10, 34], iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]],
popupAnchor: [0, -34], popupAnchor: [0, -34],
shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
shadowSize: [40, 37], shadowSize: [40, 37],

View File

@ -30,10 +30,11 @@ export class ImageMap extends LeafletMap {
width = 0; width = 0;
height = 0; height = 0;
imageUrl; imageUrl;
posFunction;
constructor($container: HTMLElement, options: UnitedMapSettings) { constructor($container: HTMLElement, options: UnitedMapSettings) {
super($container, options); super($container, options);
options.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as ((origXPos, origYPos) => { x, y }); this.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as ((origXPos, origYPos) => { x, y });
this.imageUrl = options.mapUrl; this.imageUrl = options.mapUrl;
aspectCache(this.imageUrl).subscribe(aspect => { aspectCache(this.imageUrl).subscribe(aspect => {
this.aspect = aspect; this.aspect = aspect;
@ -132,9 +133,10 @@ export class ImageMap extends LeafletMap {
convertPosition(expression): L.LatLng { convertPosition(expression): L.LatLng {
if (isNaN(expression[this.options.xPosKeyName]) || isNaN(expression[this.options.yPosKeyName])) return null; if (isNaN(expression[this.options.xPosKeyName]) || isNaN(expression[this.options.yPosKeyName])) return null;
Object.assign(expression, this.posFunction(expression[this.options.xPosKeyName], expression[this.options.yPosKeyName]))
return this.pointToLatLng( return this.pointToLatLng(
expression[this.options.xPosKeyName] * this.width, expression.x * this.width,
expression[this.options.yPosKeyName] * this.height); expression.y * this.height);
} }
pointToLatLng(x, y): L.LatLng { pointToLatLng(x, y): L.LatLng {

View File

@ -275,6 +275,16 @@ export const commonMapSettingsSchema =
type: 'string', type: 'string',
default: 'longitude' default: 'longitude'
}, },
xPosKeyName: {
title: 'X position key name',
type: 'string',
default: 'xPos'
},
yPosKeyName: {
title: 'Y position key name',
type: 'string',
default: 'yPos'
},
showLabel: { showLabel: {
title: 'Show label', title: 'Show label',
type: 'boolean', type: 'boolean',
@ -323,6 +333,21 @@ export const commonMapSettingsSchema =
title: 'Tooltip function: f(data, dsData, dsIndex)', title: 'Tooltip function: f(data, dsData, dsIndex)',
type: 'string' type: 'string'
}, },
posFunction: {
title: 'Position conversion function: f(origXPos, origYPos), should return x,y coordinates as double from 0 to 1 each',
type: 'string',
default: 'return {x: origXPos, y: origYPos};'
},
markerOffsetX: {
title: 'Marker X offset relative to position',
type: 'number',
default: 0.5
},
markerOffsetY: {
title: 'Marker Y offset relative to position',
type: 'number',
default: 1
},
color: { color: {
title: 'Color', title: 'Color',
type: 'string' type: 'string'
@ -366,14 +391,40 @@ export const commonMapSettingsSchema =
required: [] required: []
}, },
form: [ form: [
'defaultZoomLevel', {
'useDefaultCenterPosition', key: 'defaultZoomLevel',
'defaultCenterPosition', condition: 'model.provider !== "image-map"'
'fitMapBounds', },
{
key: 'useDefaultCenterPosition',
condition: 'model.provider !== "image-map"'
},
{
key: 'defaultCenterPosition',
condition: 'model.provider !== "image-map"'
},
{
key: 'fitMapBounds',
condition: 'model.provider !== "image-map"'
},
'draggableMarker', 'draggableMarker',
'disableScrollZooming', 'disableScrollZooming',
'latKeyName', {
'lngKeyName', key: 'latKeyName',
condition: 'model.provider !== "image-map"'
},
{
key: 'lngKeyName',
condition: 'model.provider !== "image-map"'
},
{
key: 'xPosKeyName',
condition: 'model.provider === "image-map"'
},
{
key: 'yPosKeyName',
condition: 'model.provider === "image-map"'
},
'showLabel', 'showLabel',
'label', 'label',
'useLabelFunction', 'useLabelFunction',
@ -407,6 +458,19 @@ export const commonMapSettingsSchema =
key: 'tooltipFunction', key: 'tooltipFunction',
type: 'javascript' type: 'javascript'
}, },
{
key: 'markerOffsetX',
condition: 'model.provider === "image-map"'
},
{
key: 'markerOffsetY',
condition: 'model.provider === "image-map"'
},
{
key: 'posFunction',
type: 'javascript',
condition: 'model.provider === "image-map"'
},
{ {
key: 'color', key: 'color',
type: 'color' type: 'color'
@ -632,123 +696,6 @@ export const imageMapSettingsSchema =
title: 'Image URL source entity attribute', title: 'Image URL source entity attribute',
type: 'string', type: 'string',
default: '' default: ''
},
disableScrollZooming: {
title: 'Disable scroll zooming',
type: 'boolean',
default: false
},
xPosKeyName: {
title: 'X position key name',
type: 'string',
default: 'xPos'
},
yPosKeyName: {
title: 'Y position key name',
type: 'string',
default: 'yPos'
},
showLabel: {
title: 'Show label',
type: 'boolean',
default: true
},
label: {
title: 'Label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )',
type: 'string',
default: '${entityName}'
},
useLabelFunction: {
title: 'Use label function',
type: 'boolean',
default: false
},
labelFunction: {
title: 'Label function: f(data, dsData, dsIndex)',
type: 'string'
},
showTooltip: {
title: 'Show tooltip',
type: 'boolean',
default: true
},
showTooltipAction: {
title: 'Action for displaying the tooltip',
type: 'string',
default: 'click'
},
autocloseTooltip: {
title: 'Auto-close tooltips',
type: 'boolean',
default: true
},
tooltipPattern: {
title: 'Tooltip (for ex. \'Text ${keyName} units.\' or <link-act name=\'my-action\'>Link text</link-act>\')',
type: 'string',
default: '<b>${entityName}</b><br/><br/><b>X Pos:</b> ${xPos:2}<br/><b>Y Pos:</b> ${yPos:2}'
},
useTooltipFunction: {
title: 'Use tooltip function',
type: 'boolean',
default: false
},
tooltipFunction: {
title: 'Tooltip function: f(data, dsData, dsIndex)',
type: 'string'
},
color: {
title: 'Color',
type: 'string'
},
posFunction: {
title: 'Position conversion function: f(origXPos, origYPos), should return x,y coordinates as double from 0 to 1 each',
type: 'string',
default: 'return {x: origXPos, y: origYPos};'
},
markerOffsetX: {
title: 'Marker X offset relative to position',
type: 'number',
default: 0.5
},
markerOffsetY: {
title: 'Marker Y offset relative to position',
type: 'number',
default: 1
},
useColorFunction: {
title: 'Use color function',
type: 'boolean',
default: false
},
colorFunction: {
title: 'Color function: f(data, dsData, dsIndex)',
type: 'string'
},
markerImage: {
title: 'Custom marker image',
type: 'string'
},
markerImageSize: {
title: 'Custom marker image size (px)',
type: 'number',
default: 34
},
useMarkerImageFunction: {
title: 'Use marker image function',
type: 'boolean',
default: false
},
markerImageFunction: {
title: 'Marker image function: f(data, images, dsData, dsIndex)',
type: 'string'
},
markerImages: {
title: 'Marker images',
type: 'array',
items: {
title: 'Marker image',
type: 'string'
}
} }
}, },
required: [] required: []
@ -759,77 +706,7 @@ export const imageMapSettingsSchema =
type: 'image' type: 'image'
}, },
'imageEntityAlias', 'imageEntityAlias',
'imageUrlAttribute', 'imageUrlAttribute'
'disableScrollZooming',
'xPosKeyName',
'yPosKeyName',
'showLabel',
'label',
'useLabelFunction',
{
key: 'labelFunction',
type: 'javascript'
},
'showTooltip',
{
key: 'showTooltipAction',
type: 'rc-select',
multiple: false,
items: [
{
value: 'click',
label: 'Show tooltip on click (Default)'
},
{
value: 'hover',
label: 'Show tooltip on hover'
}
]
},
'autocloseTooltip',
{
key: 'tooltipPattern',
type: 'textarea'
},
'useTooltipFunction',
{
key: 'tooltipFunction',
type: 'javascript'
},
{
key: 'color',
type: 'color'
},
{
key: 'posFunction',
type: 'javascript'
},
'markerOffsetX',
'markerOffsetY',
'useColorFunction',
{
key: 'colorFunction',
type: 'javascript'
},
{
key: 'markerImage',
type: 'image'
},
'markerImageSize',
'useMarkerImageFunction',
{
key: 'markerImageFunction',
type: 'javascript'
},
{
key: 'markerImages',
items: [
{
key: 'markerImages[]',
type: 'image'
}
]
}
] ]
}; };