Commit adc982923da5f6c3433518eb73147d06f822e0c1

Authored by Vladyslav
Committed by GitHub
1 parent f7efb790

[3.0] Improvment image map (#2729)

* Add support setting position function

* Improved setting image map

* Add support setting offset marker
@@ -94,6 +94,8 @@ export type MarkerSettings = { @@ -94,6 +94,8 @@ export type MarkerSettings = {
94 tooltipFunction: GenericFunction; 94 tooltipFunction: GenericFunction;
95 labelFunction: GenericFunction; 95 labelFunction: GenericFunction;
96 markerImageFunction?: MarkerImageFunction; 96 markerImageFunction?: MarkerImageFunction;
  97 + markerOffsetX: number;
  98 + markerOffsetY: number;
97 } 99 }
98 100
99 export interface FormattedData { 101 export interface FormattedData {
@@ -96,7 +96,7 @@ export class MapWidgetController implements MapWidgetInterface { @@ -96,7 +96,7 @@ export class MapWidgetController implements MapWidgetInterface {
96 const schema = initSchema(); 96 const schema = initSchema();
97 addToSchema(schema, this.getProvidersSchema(mapProvider)); 97 addToSchema(schema, this.getProvidersSchema(mapProvider));
98 addGroupInfo(schema, 'Map Provider Settings'); 98 addGroupInfo(schema, 'Map Provider Settings');
99 - addToSchema(schema, addCondition(commonMapSettingsSchema, 'model.provider !== "image-map"')); 99 + addToSchema(schema, commonMapSettingsSchema);
100 addGroupInfo(schema, 'Common Map Settings'); 100 addGroupInfo(schema, 'Common Map Settings');
101 addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon'])); 101 addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon']));
102 addGroupInfo(schema, 'Polygon Settings'); 102 addGroupInfo(schema, 'Polygon Settings');
@@ -18,10 +18,12 @@ import L, { LeafletMouseEvent } from 'leaflet'; @@ -18,10 +18,12 @@ import L, { LeafletMouseEvent } from 'leaflet';
18 import { FormattedData, MarkerSettings } from './map-models'; 18 import { FormattedData, MarkerSettings } from './map-models';
19 import { aspectCache, createTooltip, parseWithTranslation, safeExecute } from './maps-utils'; 19 import { aspectCache, createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
20 import tinycolor from 'tinycolor2'; 20 import tinycolor from 'tinycolor2';
  21 +import { isDefined } from '@core/utils';
21 22
22 export class Marker { 23 export class Marker {
23 leafletMarker: L.Marker; 24 leafletMarker: L.Marker;
24 tooltipOffset: [number, number]; 25 tooltipOffset: [number, number];
  26 + markerOffset: [number, number];
25 tooltip: L.Popup; 27 tooltip: L.Popup;
26 location: L.LatLngExpression; 28 location: L.LatLngExpression;
27 data: FormattedData; 29 data: FormattedData;
@@ -34,9 +36,14 @@ export class Marker { @@ -34,9 +36,14 @@ export class Marker {
34 draggable: settings.draggableMarker 36 draggable: settings.draggableMarker
35 }); 37 });
36 38
  39 + this.markerOffset = [
  40 + isDefined(settings.markerOffsetX) ? settings.markerOffsetX : 0.5,
  41 + isDefined(settings.markerOffsetY) ? settings.markerOffsetY : 1,
  42 + ];
  43 +
37 this.createMarkerIcon((iconInfo) => { 44 this.createMarkerIcon((iconInfo) => {
38 this.leafletMarker.setIcon(iconInfo.icon); 45 this.leafletMarker.setIcon(iconInfo.icon);
39 - this.tooltipOffset = [0, -iconInfo.size[1] + 10]; 46 + this.tooltipOffset = [0, -iconInfo.size[1] * this.markerOffset[1] + 10];
40 this.updateMarkerLabel(settings); 47 this.updateMarkerLabel(settings);
41 }); 48 });
42 49
@@ -95,7 +102,7 @@ export class Marker { @@ -95,7 +102,7 @@ export class Marker {
95 updateMarkerIcon(settings: MarkerSettings) { 102 updateMarkerIcon(settings: MarkerSettings) {
96 this.createMarkerIcon((iconInfo) => { 103 this.createMarkerIcon((iconInfo) => {
97 this.leafletMarker.setIcon(iconInfo.icon); 104 this.leafletMarker.setIcon(iconInfo.icon);
98 - this.tooltipOffset = [0, -iconInfo.size[1] + 10]; 105 + this.tooltipOffset = [0, -iconInfo.size[1] * this.markerOffset[1] + 10];
99 this.updateMarkerLabel(settings); 106 this.updateMarkerLabel(settings);
100 }); 107 });
101 } 108 }
@@ -130,7 +137,7 @@ export class Marker { @@ -130,7 +137,7 @@ export class Marker {
130 const icon = L.icon({ 137 const icon = L.icon({
131 iconUrl: currentImage.url, 138 iconUrl: currentImage.url,
132 iconSize: [width, height], 139 iconSize: [width, height],
133 - iconAnchor: [width / 2, height], 140 + iconAnchor: [width * this.markerOffset[0], height * this.markerOffset[1]],
134 popupAnchor: [0, -height] 141 popupAnchor: [0, -height]
135 }); 142 });
136 const iconInfo = { 143 const iconInfo = {
@@ -152,7 +159,7 @@ export class Marker { @@ -152,7 +159,7 @@ export class Marker {
152 const icon = L.icon({ 159 const icon = L.icon({
153 iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color, 160 iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color,
154 iconSize: [21, 34], 161 iconSize: [21, 34],
155 - iconAnchor: [10, 34], 162 + iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]],
156 popupAnchor: [0, -34], 163 popupAnchor: [0, -34],
157 shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', 164 shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
158 shadowSize: [40, 37], 165 shadowSize: [40, 37],
@@ -30,10 +30,11 @@ export class ImageMap extends LeafletMap { @@ -30,10 +30,11 @@ export class ImageMap extends LeafletMap {
30 width = 0; 30 width = 0;
31 height = 0; 31 height = 0;
32 imageUrl; 32 imageUrl;
  33 + posFunction;
33 34
34 constructor($container: HTMLElement, options: UnitedMapSettings) { 35 constructor($container: HTMLElement, options: UnitedMapSettings) {
35 super($container, options); 36 super($container, options);
36 - options.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as ((origXPos, origYPos) => { x, y }); 37 + this.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as ((origXPos, origYPos) => { x, y });
37 this.imageUrl = options.mapUrl; 38 this.imageUrl = options.mapUrl;
38 aspectCache(this.imageUrl).subscribe(aspect => { 39 aspectCache(this.imageUrl).subscribe(aspect => {
39 this.aspect = aspect; 40 this.aspect = aspect;
@@ -132,9 +133,10 @@ export class ImageMap extends LeafletMap { @@ -132,9 +133,10 @@ export class ImageMap extends LeafletMap {
132 133
133 convertPosition(expression): L.LatLng { 134 convertPosition(expression): L.LatLng {
134 if (isNaN(expression[this.options.xPosKeyName]) || isNaN(expression[this.options.yPosKeyName])) return null; 135 if (isNaN(expression[this.options.xPosKeyName]) || isNaN(expression[this.options.yPosKeyName])) return null;
  136 + Object.assign(expression, this.posFunction(expression[this.options.xPosKeyName], expression[this.options.yPosKeyName]))
135 return this.pointToLatLng( 137 return this.pointToLatLng(
136 - expression[this.options.xPosKeyName] * this.width,  
137 - expression[this.options.yPosKeyName] * this.height); 138 + expression.x * this.width,
  139 + expression.y * this.height);
138 } 140 }
139 141
140 pointToLatLng(x, y): L.LatLng { 142 pointToLatLng(x, y): L.LatLng {
@@ -275,6 +275,16 @@ export const commonMapSettingsSchema = @@ -275,6 +275,16 @@ export const commonMapSettingsSchema =
275 type: 'string', 275 type: 'string',
276 default: 'longitude' 276 default: 'longitude'
277 }, 277 },
  278 + xPosKeyName: {
  279 + title: 'X position key name',
  280 + type: 'string',
  281 + default: 'xPos'
  282 + },
  283 + yPosKeyName: {
  284 + title: 'Y position key name',
  285 + type: 'string',
  286 + default: 'yPos'
  287 + },
278 showLabel: { 288 showLabel: {
279 title: 'Show label', 289 title: 'Show label',
280 type: 'boolean', 290 type: 'boolean',
@@ -323,6 +333,21 @@ export const commonMapSettingsSchema = @@ -323,6 +333,21 @@ export const commonMapSettingsSchema =
323 title: 'Tooltip function: f(data, dsData, dsIndex)', 333 title: 'Tooltip function: f(data, dsData, dsIndex)',
324 type: 'string' 334 type: 'string'
325 }, 335 },
  336 + posFunction: {
  337 + title: 'Position conversion function: f(origXPos, origYPos), should return x,y coordinates as double from 0 to 1 each',
  338 + type: 'string',
  339 + default: 'return {x: origXPos, y: origYPos};'
  340 + },
  341 + markerOffsetX: {
  342 + title: 'Marker X offset relative to position',
  343 + type: 'number',
  344 + default: 0.5
  345 + },
  346 + markerOffsetY: {
  347 + title: 'Marker Y offset relative to position',
  348 + type: 'number',
  349 + default: 1
  350 + },
326 color: { 351 color: {
327 title: 'Color', 352 title: 'Color',
328 type: 'string' 353 type: 'string'
@@ -366,14 +391,40 @@ export const commonMapSettingsSchema = @@ -366,14 +391,40 @@ export const commonMapSettingsSchema =
366 required: [] 391 required: []
367 }, 392 },
368 form: [ 393 form: [
369 - 'defaultZoomLevel',  
370 - 'useDefaultCenterPosition',  
371 - 'defaultCenterPosition',  
372 - 'fitMapBounds', 394 + {
  395 + key: 'defaultZoomLevel',
  396 + condition: 'model.provider !== "image-map"'
  397 + },
  398 + {
  399 + key: 'useDefaultCenterPosition',
  400 + condition: 'model.provider !== "image-map"'
  401 + },
  402 + {
  403 + key: 'defaultCenterPosition',
  404 + condition: 'model.provider !== "image-map"'
  405 + },
  406 + {
  407 + key: 'fitMapBounds',
  408 + condition: 'model.provider !== "image-map"'
  409 + },
373 'draggableMarker', 410 'draggableMarker',
374 'disableScrollZooming', 411 'disableScrollZooming',
375 - 'latKeyName',  
376 - 'lngKeyName', 412 + {
  413 + key: 'latKeyName',
  414 + condition: 'model.provider !== "image-map"'
  415 + },
  416 + {
  417 + key: 'lngKeyName',
  418 + condition: 'model.provider !== "image-map"'
  419 + },
  420 + {
  421 + key: 'xPosKeyName',
  422 + condition: 'model.provider === "image-map"'
  423 + },
  424 + {
  425 + key: 'yPosKeyName',
  426 + condition: 'model.provider === "image-map"'
  427 + },
377 'showLabel', 428 'showLabel',
378 'label', 429 'label',
379 'useLabelFunction', 430 'useLabelFunction',
@@ -408,6 +459,19 @@ export const commonMapSettingsSchema = @@ -408,6 +459,19 @@ export const commonMapSettingsSchema =
408 type: 'javascript' 459 type: 'javascript'
409 }, 460 },
410 { 461 {
  462 + key: 'markerOffsetX',
  463 + condition: 'model.provider === "image-map"'
  464 + },
  465 + {
  466 + key: 'markerOffsetY',
  467 + condition: 'model.provider === "image-map"'
  468 + },
  469 + {
  470 + key: 'posFunction',
  471 + type: 'javascript',
  472 + condition: 'model.provider === "image-map"'
  473 + },
  474 + {
411 key: 'color', 475 key: 'color',
412 type: 'color' 476 type: 'color'
413 }, 477 },
@@ -632,123 +696,6 @@ export const imageMapSettingsSchema = @@ -632,123 +696,6 @@ export const imageMapSettingsSchema =
632 title: 'Image URL source entity attribute', 696 title: 'Image URL source entity attribute',
633 type: 'string', 697 type: 'string',
634 default: '' 698 default: ''
635 - },  
636 - disableScrollZooming: {  
637 - title: 'Disable scroll zooming',  
638 - type: 'boolean',  
639 - default: false  
640 - },  
641 - xPosKeyName: {  
642 - title: 'X position key name',  
643 - type: 'string',  
644 - default: 'xPos'  
645 - },  
646 - yPosKeyName: {  
647 - title: 'Y position key name',  
648 - type: 'string',  
649 - default: 'yPos'  
650 - },  
651 - showLabel: {  
652 - title: 'Show label',  
653 - type: 'boolean',  
654 - default: true  
655 - },  
656 - label: {  
657 - title: 'Label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )',  
658 - type: 'string',  
659 - default: '${entityName}'  
660 - },  
661 - useLabelFunction: {  
662 - title: 'Use label function',  
663 - type: 'boolean',  
664 - default: false  
665 - },  
666 - labelFunction: {  
667 - title: 'Label function: f(data, dsData, dsIndex)',  
668 - type: 'string'  
669 - },  
670 - showTooltip: {  
671 - title: 'Show tooltip',  
672 - type: 'boolean',  
673 - default: true  
674 - },  
675 - showTooltipAction: {  
676 - title: 'Action for displaying the tooltip',  
677 - type: 'string',  
678 - default: 'click'  
679 - },  
680 - autocloseTooltip: {  
681 - title: 'Auto-close tooltips',  
682 - type: 'boolean',  
683 - default: true  
684 - },  
685 - tooltipPattern: {  
686 - title: 'Tooltip (for ex. \'Text ${keyName} units.\' or <link-act name=\'my-action\'>Link text</link-act>\')',  
687 - type: 'string',  
688 - default: '<b>${entityName}</b><br/><br/><b>X Pos:</b> ${xPos:2}<br/><b>Y Pos:</b> ${yPos:2}'  
689 - },  
690 - useTooltipFunction: {  
691 - title: 'Use tooltip function',  
692 - type: 'boolean',  
693 - default: false  
694 - },  
695 - tooltipFunction: {  
696 - title: 'Tooltip function: f(data, dsData, dsIndex)',  
697 - type: 'string'  
698 - },  
699 - color: {  
700 - title: 'Color',  
701 - type: 'string'  
702 - },  
703 - posFunction: {  
704 - title: 'Position conversion function: f(origXPos, origYPos), should return x,y coordinates as double from 0 to 1 each',  
705 - type: 'string',  
706 - default: 'return {x: origXPos, y: origYPos};'  
707 - },  
708 - markerOffsetX: {  
709 - title: 'Marker X offset relative to position',  
710 - type: 'number',  
711 - default: 0.5  
712 - },  
713 - markerOffsetY: {  
714 - title: 'Marker Y offset relative to position',  
715 - type: 'number',  
716 - default: 1  
717 - },  
718 - useColorFunction: {  
719 - title: 'Use color function',  
720 - type: 'boolean',  
721 - default: false  
722 - },  
723 - colorFunction: {  
724 - title: 'Color function: f(data, dsData, dsIndex)',  
725 - type: 'string'  
726 - },  
727 - markerImage: {  
728 - title: 'Custom marker image',  
729 - type: 'string'  
730 - },  
731 - markerImageSize: {  
732 - title: 'Custom marker image size (px)',  
733 - type: 'number',  
734 - default: 34  
735 - },  
736 - useMarkerImageFunction: {  
737 - title: 'Use marker image function',  
738 - type: 'boolean',  
739 - default: false  
740 - },  
741 - markerImageFunction: {  
742 - title: 'Marker image function: f(data, images, dsData, dsIndex)',  
743 - type: 'string'  
744 - },  
745 - markerImages: {  
746 - title: 'Marker images',  
747 - type: 'array',  
748 - items: {  
749 - title: 'Marker image',  
750 - type: 'string'  
751 - }  
752 } 699 }
753 }, 700 },
754 required: [] 701 required: []
@@ -759,77 +706,7 @@ export const imageMapSettingsSchema = @@ -759,77 +706,7 @@ export const imageMapSettingsSchema =
759 type: 'image' 706 type: 'image'
760 }, 707 },
761 'imageEntityAlias', 708 'imageEntityAlias',
762 - 'imageUrlAttribute',  
763 - 'disableScrollZooming',  
764 - 'xPosKeyName',  
765 - 'yPosKeyName',  
766 - 'showLabel',  
767 - 'label',  
768 - 'useLabelFunction',  
769 - {  
770 - key: 'labelFunction',  
771 - type: 'javascript'  
772 - },  
773 - 'showTooltip',  
774 - {  
775 - key: 'showTooltipAction',  
776 - type: 'rc-select',  
777 - multiple: false,  
778 - items: [  
779 - {  
780 - value: 'click',  
781 - label: 'Show tooltip on click (Default)'  
782 - },  
783 - {  
784 - value: 'hover',  
785 - label: 'Show tooltip on hover'  
786 - }  
787 - ]  
788 - },  
789 - 'autocloseTooltip',  
790 - {  
791 - key: 'tooltipPattern',  
792 - type: 'textarea'  
793 - },  
794 - 'useTooltipFunction',  
795 - {  
796 - key: 'tooltipFunction',  
797 - type: 'javascript'  
798 - },  
799 - {  
800 - key: 'color',  
801 - type: 'color'  
802 - },  
803 - {  
804 - key: 'posFunction',  
805 - type: 'javascript'  
806 - },  
807 - 'markerOffsetX',  
808 - 'markerOffsetY',  
809 - 'useColorFunction',  
810 - {  
811 - key: 'colorFunction',  
812 - type: 'javascript'  
813 - },  
814 - {  
815 - key: 'markerImage',  
816 - type: 'image'  
817 - },  
818 - 'markerImageSize',  
819 - 'useMarkerImageFunction',  
820 - {  
821 - key: 'markerImageFunction',  
822 - type: 'javascript'  
823 - },  
824 - {  
825 - key: 'markerImages',  
826 - items: [  
827 - {  
828 - key: 'markerImages[]',  
829 - type: 'image'  
830 - }  
831 - ]  
832 - } 709 + 'imageUrlAttribute'
833 ] 710 ]
834 }; 711 };
835 712