@sapui5/sap.ui.vbm 1.140.0 → 1.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.ui.vbm",
3
- "version": "1.140.0",
3
+ "version": "1.141.0",
4
4
  "description": "SAPUI5 Library sap.ui.vbm",
5
5
  "homepage": "https://sap.github.io/ui5-tooling/pages/SAPUI5/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -3,7 +3,7 @@
3
3
  <name>sap.ui.vbm</name>
4
4
  <vendor>SAP SE</vendor>
5
5
  <copyright>SAP UI development toolkit for HTML5 (SAPUI5) (c) Copyright 2009-2012 SAP AG. All rights reserved</copyright>
6
- <version>1.140.0</version>
6
+ <version>1.141.0</version>
7
7
 
8
8
  <documentation>SAP UI library: sap.ui.vbm</documentation>
9
9
 
@@ -24,7 +24,7 @@ sap.ui.define([
24
24
  * @param {string} [sId] id for the new control, generated automatically if no id is given
25
25
  * @param {object} [mSettings] initial settings for the new object
26
26
  * @author SAP SE
27
- * @version 1.140.0
27
+ * @version 1.141.0
28
28
  * @extends sap.ui.core.Element
29
29
  * @constructor
30
30
  * @public
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  * @param {string} [sId] id for the new control, generated automatically if no id is given
48
48
  * @param {object} [mSettings] initial settings for the new object
49
49
  * @author SAP SE
50
- * @version 1.140.0
50
+ * @version 1.141.0
51
51
  * @extends sap.ui.core.Element
52
52
  * @constructor
53
53
  * @public
@@ -23,7 +23,7 @@ sap.ui.define([
23
23
  *
24
24
  * @public
25
25
  * @author SAP SE
26
- * @version 1.140.0
26
+ * @version 1.141.0
27
27
  * @extends sap.ui.core.Control
28
28
  * @alias sap.ui.vbm.Viewport
29
29
  */
@@ -22,7 +22,7 @@ sap.ui.define([
22
22
  *
23
23
  * @private
24
24
  * @author SAP SE
25
- * @version 1.140.0
25
+ * @version 1.141.0
26
26
  * @alias sap.ui.vbm.adapter3d.ColladaBounds
27
27
  */
28
28
  var ColladaBounds = BaseObject.extend("sap.ui.vbm.adapter3d.ColladaBounds", /** @lends sap.ui.vbm.adapter3d.ColladaBounds.prototype */ {
@@ -83,7 +83,7 @@ sap.ui.define([
83
83
  *
84
84
  * @private
85
85
  * @author SAP SE
86
- * @version 1.140.0
86
+ * @version 1.141.0
87
87
  * @alias sap.ui.vbm.adapter3d.DragDropHandler
88
88
  */
89
89
  var DragDropHandler = BaseObject.extend("sap.ui.vbm.adapter3d.DragDropHandler", /** @lends sap.ui.vbm.adapter3d.DragDropHandler.prototype */ {
@@ -29,7 +29,7 @@ sap.ui.define([
29
29
  *
30
30
  * @private
31
31
  * @author SAP SE
32
- * @version 1.140.0
32
+ * @version 1.141.0
33
33
  * @alias sap.ui.vbm.adapter3d.ModelHandler
34
34
  */
35
35
  var ModelHandler = BaseObject.extend("sap.ui.vbm.adapter3d.ModelHandler", /** @lends sap.ui.vbm.adapter3d.ModelHandler.prototype */ {
@@ -377,7 +377,7 @@ sap.ui.define([
377
377
  *
378
378
  * @private
379
379
  * @author SAP SE
380
- * @version 1.140.0
380
+ * @version 1.141.0
381
381
  * @alias sap.ui.vbm.adapter3d.ObjectFactory
382
382
  */
383
383
  var ObjectFactory = BaseObject.extend("sap.ui.vbm.adapter3d.ObjectFactory", /** @lends sap.ui.vbm.adapter3d.ObjectFactory.prototype */ {});
@@ -32,7 +32,7 @@ sap.ui.define([
32
32
  *
33
33
  * @private
34
34
  * @author SAP SE
35
- * @version 1.140.0
35
+ * @version 1.141.0
36
36
  * @alias sap.ui.vbm.adapter3d.PolygonHandler
37
37
  */
38
38
  var PolygonHandler = BaseObject.extend("sap.ui.vbm.adapter3d.PolygonHandler", /** @lends sap.ui.vbm.adapter3d.PolygonHandler.prototype */ {
@@ -7,7 +7,7 @@ sap.ui.define([
7
7
  var Vector2 = THREE.Vector2;
8
8
  var _frustum = new THREE.Frustum;
9
9
  var _center = new THREE.Vector3;
10
- var _tmpPoint = new THREE.Vector3;
10
+ //var _tmpPoint = new THREE.Vector3;
11
11
  var _vecNear = new THREE.Vector3;
12
12
  var _vecTopLeft = new THREE.Vector3;
13
13
  var _vecTopRight = new THREE.Vector3;
@@ -39,7 +39,7 @@ sap.ui.define([
39
39
  *
40
40
  * @private
41
41
  * @author SAP SE
42
- * @version 1.140.0
42
+ * @version 1.141.0
43
43
  * @alias sap.ui.vbm.adapter3d.RectangleTracker
44
44
  */
45
45
  var RectangleTracker = BaseObject.extend("sap.ui.vbm.adapter3d.RectangleTracker", /** @lends sap.ui.vbm.adapter3d.RectangleTracker.prototype */ {
@@ -148,6 +148,9 @@ sap.ui.define([
148
148
  };
149
149
 
150
150
  RectangleTracker.prototype._onPointerDown = function (event) {
151
+ if (event.button !== 0) {
152
+ return; // Don't start selection if it's not the left button
153
+ }
151
154
  this._updateController(true);
152
155
  this.onSelectStart(event);
153
156
  var that = this;
@@ -420,6 +423,14 @@ sap.ui.define([
420
423
  this.startPoint = startPoint || this.startPoint;
421
424
  this.endPoint = endPoint || this.endPoint;
422
425
  this.collection = [];
426
+ const dx = Math.abs(endPoint.x - startPoint.x);
427
+ const dy = Math.abs(endPoint.y - startPoint.y);
428
+
429
+ // if less than 2-3 pixels movement => treat as click, skip updateFrustum
430
+ if (dx < 0.002 && dy < 0.002) {
431
+ // 👉 handle as simple click (use raycaster for single object select)
432
+ return;
433
+ }
423
434
  this.updateFrustum(this.startPoint, this.endPoint);
424
435
  this.searchChildInFrustum(_frustum, this._scene);
425
436
  this._scene.remove(this._planeMesh);
@@ -447,52 +458,46 @@ sap.ui.define([
447
458
 
448
459
  if (this._camera.isPerspectiveCamera) {
449
460
 
450
- _tmpPoint = startPoint;
451
- _tmpPoint.x = Math.min(startPoint.x, endPoint.x);
452
- _tmpPoint.y = Math.max(startPoint.y, endPoint.y);
453
- endPoint.x = Math.max(startPoint.x, endPoint.x);
454
- endPoint.y = Math.min(startPoint.y, endPoint.y);
461
+ // Normalize rectangle regardless of drag direction
462
+ var minX = Math.min(startPoint.x, endPoint.x);
463
+ var maxX = Math.max(startPoint.x, endPoint.x);
464
+ var minY = Math.min(startPoint.y, endPoint.y);
465
+ var maxY = Math.max(startPoint.y, endPoint.y);
455
466
 
467
+ // Define corners in NDC (normalized device coordinates)
468
+ _vecTopLeft.set(minX, maxY, 0);
469
+ _vecTopRight.set(maxX, maxY, 0);
470
+ _vecDownRight.set(maxX, minY, 0);
471
+ _vecDownLeft.set(minX, minY, 0);
472
+
473
+ // Camera position
456
474
  _vecNear.setFromMatrixPosition(this._camera.matrixWorld);
457
- _vecTopLeft.copy(_tmpPoint);
458
- _vecTopRight.set(endPoint.x, _tmpPoint.y, 0);
459
- _vecDownRight.copy(endPoint);
460
- _vecDownLeft.set(_tmpPoint.x, endPoint.y, 0);
461
475
 
462
476
  _vecTopLeft.unproject(this._camera);
463
477
  _vecTopRight.unproject(this._camera);
464
478
  _vecDownRight.unproject(this._camera);
465
479
  _vecDownLeft.unproject(this._camera);
466
480
 
467
- _vectemp1.copy(_vecTopLeft).sub(_vecNear);
468
- _vectemp2.copy(_vecTopRight).sub(_vecNear);
469
- _vectemp3.copy(_vecDownRight).sub(_vecNear);
470
- _vectemp1.normalize();
471
- _vectemp2.normalize();
472
- _vectemp3.normalize();
473
-
474
-
475
- _vectemp1.multiplyScalar(this.deep);
476
- _vectemp2.multiplyScalar(this.deep);
477
- _vectemp3.multiplyScalar(this.deep);
478
- _vectemp4.multiplyScalar(this.deep);
479
- _vectemp1.sub(_vecNear);
480
- _vectemp2.sub(_vecNear);
481
- _vectemp3.sub(_vecNear);
481
+ // Far points (deep into the scene)
482
+ _vectemp1.copy(_vecTopLeft).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
483
+ _vectemp2.copy(_vecTopRight).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
484
+ _vectemp3.copy(_vecDownRight).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
485
+ _vectemp4.copy(_vecDownLeft).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
482
486
 
483
487
  var planes = _frustum.planes;
484
488
 
485
- planes[0].setFromCoplanarPoints(_vecNear, _vecTopLeft, _vecTopRight);
486
- planes[1].setFromCoplanarPoints(_vecNear, _vecTopRight, _vecDownRight);
487
- planes[2].setFromCoplanarPoints(_vecDownRight, _vecDownLeft, _vecNear);
488
- planes[3].setFromCoplanarPoints(_vecDownLeft, _vecTopLeft, _vecNear);
489
- planes[4].setFromCoplanarPoints(_vecTopRight, _vecDownRight, _vecDownLeft);
490
- planes[5].setFromCoplanarPoints(_vectemp3, _vectemp2, _vectemp1);
489
+ // Build planes around the selection frustum
490
+ planes[0].setFromCoplanarPoints(_vecNear, _vecTopLeft, _vecTopRight); // top
491
+ planes[1].setFromCoplanarPoints(_vecNear, _vecTopRight, _vecDownRight); // right
492
+ planes[2].setFromCoplanarPoints(_vecNear, _vecDownRight, _vecDownLeft); // bottom
493
+ planes[3].setFromCoplanarPoints(_vecNear, _vecDownLeft, _vecTopLeft); // left
494
+ planes[4].setFromCoplanarPoints(_vecTopRight, _vecDownRight, _vecDownLeft); // near plane
495
+ planes[5].setFromCoplanarPoints(_vectemp3, _vectemp2, _vectemp1); // far plane
491
496
  planes[5].normal.multiplyScalar(-1);
492
497
  }
493
498
 
494
-
495
- }
499
+ return _frustum; // ✅ return the frustum so selecting() can use it
500
+ };
496
501
 
497
502
  RectangleTracker.prototype.searchChildInFrustum = function (frustum, object) {
498
503
  var count = 0;
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  *
48
48
  * @private
49
49
  * @author SAP SE
50
- * @version 1.140.0
50
+ * @version 1.141.0
51
51
  * @alias sap.ui.vbm.adapter3d.SceneBuilder
52
52
  */
53
53
  var SceneBuilder = BaseObject.extend("sap.ui.vbm.adapter3d.SceneBuilder", /** @lends sap.ui.vbm.adapter3d.SceneBuilder.prototype */ {
@@ -56,7 +56,7 @@ sap.ui.define([
56
56
  *
57
57
  * @private
58
58
  * @author SAP SE
59
- * @version 1.140.0
59
+ * @version 1.141.0
60
60
  * @alias sap.ui.vbm.adapter3d.VBIJSONParser
61
61
  */
62
62
  var VBIJSONParser = BaseObject.extend("sap.ui.vbm.adapter3d.VBIJSONParser", /** @lends sap.ui.vbm.adapter3d.VBIJSONParser.prototype */ {
@@ -20,7 +20,7 @@ sap.ui.define([
20
20
  * @namespace
21
21
  * @alias sap.ui.vbm
22
22
  * @author SAP SE
23
- * @version 1.140.0
23
+ * @version 1.141.0
24
24
  * @public
25
25
  */
26
26
 
@@ -46,7 +46,7 @@ sap.ui.define([
46
46
  "sap.ui.vbm.ClusterBase", "sap.ui.vbm.ClusterTree", "sap.ui.vbm.ClusterGrid", "sap.ui.vbm.ClusterDistance", "sap.ui.vbm.Heatmap",
47
47
  "sap.ui.vbm.HeatPoint", "sap.ui.vbm.ClusterContainer", "sap.ui.vbm.Adapter", "sap.ui.vbm.Adapter3D"
48
48
  ],
49
- version: "1.140.0"
49
+ version: "1.141.0"
50
50
  });
51
51
 
52
52
  sap.ui.loader.config({
@@ -163,7 +163,9 @@ sap.ui.define([
163
163
  let markerCoordinates = marker.geometry.coordinates;
164
164
  if (marker.geometry.type === 'Point') {
165
165
  // create a DOM element for the marker (parent div)
166
- const el = VectorUtils.createSpotElement(marker);
166
+ let createdSpot = VectorUtils.createSpotElement(marker, spotid);
167
+ const el = createdSpot.spotEl;
168
+ spotid = createdSpot.spotId;
167
169
  if (marker.properties.Label) {
168
170
  const child_e1 = VectorUtils.createMarkerLabel(marker.properties.Label, marker.properties.LabelBGColor);
169
171
  el.appendChild(child_e1);
@@ -180,7 +182,7 @@ sap.ui.define([
180
182
  let spot = new maplibregl.Marker({
181
183
  element: el,
182
184
  draggable: true,
183
- offset: [0, -20]
185
+ anchor: 'bottom'
184
186
  }).setLngLat(marker.geometry.coordinates)
185
187
  .on('dragend', onDragEnd)
186
188
  .addTo(map);
@@ -514,15 +516,21 @@ sap.ui.define([
514
516
  }
515
517
  } else if (marker.geometry.type == "LineString") {
516
518
 
517
- const colorStr = marker.properties.LineColor;
518
- let textColor = '#000000'; // Default color
519
-
520
- if (colorStr) {
521
- const [r, g, b, a] = VectorUtils.parseRGBAString(colorStr);
522
- textColor = VectorUtils.getContrastTextColor(r, g, b);
523
- marker.properties.labelHaloColor = `rgba(${r}, ${g}, ${b}, ${a})`;
519
+ if (marker.properties.Label) {
520
+ const midpoint = getMidpoint(marker.geometry.coordinates);
521
+
522
+ const routeLabelEl = VectorUtils.createRouteLabel(
523
+ marker.properties.Label,
524
+ marker.properties.LabelBGColor
525
+ );
526
+
527
+ new maplibregl.Marker({
528
+ element: routeLabelEl,
529
+ anchor: 'left',
530
+ })
531
+ .setLngLat(midpoint)
532
+ .addTo(map);
524
533
  }
525
- marker.properties.textColor = textColor;
526
534
  const coords = marker.geometry.coordinates;
527
535
  const startCoord = coords[0]; // First coordinate
528
536
  const endCoord = coords[coords.length - 1]; // Last coordinate
@@ -621,29 +629,17 @@ sap.ui.define([
621
629
  },
622
630
  'filter': ['==', '$type', 'LineString']
623
631
  });
624
-
625
- map.addLayer({
626
- id: 'line-labels',
627
- type: 'symbol',
628
- source: 'geojson-source',
629
- layout: {
630
- 'symbol-placement': 'line-center',
631
- 'text-field': ['get', 'Label'],
632
- 'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
633
- 'text-size': 14,
634
- 'text-rotation-alignment': 'map',
635
- 'text-keep-upright': true
636
- },
637
- paint: {
638
- 'text-color': ['get', 'lineLabelTextColor'],
639
- 'text-halo-color': ['get', 'labelHaloColor'],
640
- 'text-halo-width': 4,
641
- 'text-halo-blur': 0.8,
642
- 'text-opacity': ['get', 'opacity']
643
- },
644
-
645
- filter: ['all', ['==', ['get', 'ShowLabel'], true]]
646
- });
632
+
633
+ function getMidpoint(coords) {
634
+ if (coords.length < 2) return coords[0];
635
+
636
+ const start = coords[0];
637
+ const end = coords[coords.length - 1];
638
+ const midLng = (start[0] + end[0]) / 2;
639
+ const midLat = (start[1] + end[1]) / 2;
640
+
641
+ return [midLng, midLat];
642
+ }
647
643
 
648
644
  // Create a new FeatureCollection for the points
649
645
  const pointGeoJSON = {
@@ -933,7 +929,7 @@ sap.ui.define([
933
929
  PayloadGenerator.onMapContextMenu(coords, currentZoom, currentCenter, screenX, screenY);
934
930
  }
935
931
  };
936
-
932
+
937
933
  var that = this;
938
934
  map.on('idle', () => {
939
935
  const container = map.getContainer();
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.140.0
15
+ * @version 1.141.0
16
16
  * @alias sap.ui.vbm.vector.PayloadGenerator
17
17
  */
18
18
  var adapter = {};
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.140.0
15
+ * @version 1.141.0
16
16
  * @alias sap.ui.vbm.vector.RectangularSelection
17
17
  */
18
18
 
@@ -223,12 +223,10 @@ sap.ui.define([
223
223
  "Image": currSpot.I ? currSpot.I : "",
224
224
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
225
225
  "Key": currSpot.K ? currSpot.K : "",
226
- "Scale": currSpot.S ? currSpot.S : "",
226
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
227
227
  "DisplayRole": currSpot.R ? currSpot.R : "",
228
228
  "DragData": currSpot.DD ? currSpot.DD : "",
229
229
  "Alignment": currSpot.AL ? currSpot.AL : "",
230
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
231
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
232
230
  "menu": menus,
233
231
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
234
232
  };
@@ -273,15 +271,12 @@ sap.ui.define([
273
271
  "Image": currSpot.I ? currSpot.I : "",
274
272
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
275
273
  "Key": currSpot.K ? currSpot.K : "",
276
- "Scale": currSpot.S ? currSpot.S : "",
274
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
277
275
  "DisplayRole": currSpot.R ? currSpot.R : "",
278
276
  "DragData": currSpot.DD ? currSpot.DD : "",
279
277
  "Alignment": currSpot.AL ? currSpot.AL : "",
280
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
281
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
282
278
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
283
-
284
- };
279
+ };
285
280
 
286
281
  let coord_array = currSpot.A.split(";");
287
282
 
@@ -361,7 +356,6 @@ sap.ui.define([
361
356
  routeProperties["opacity"] = opacity;
362
357
  }
363
358
 
364
- //itearate through the route points and add the coordinates to the GeoJSON
365
359
  let coord_array = currRoute.H.split(";");
366
360
  let coord_collection = [];
367
361
 
@@ -369,6 +363,7 @@ sap.ui.define([
369
363
  coord_collection.push([Number(coord_array[i]), Number(coord_array[i + 1])])
370
364
  }
371
365
 
366
+
372
367
  let geometry = {
373
368
  "coordinates": coord_collection,
374
369
  "type": "LineString"
@@ -814,6 +809,13 @@ sap.ui.define([
814
809
  }
815
810
  }
816
811
 
812
+ if (obj.SAPVB.Data.Set && (typeof obj.SAPVB.Data.Set === 'object') && !(jQuery.isEmptyObject(obj.SAPVB.Data.Set))) {
813
+ if (!Array.isArray(obj.SAPVB.Data.Set) && !(obj.SAPVB.Data.Set.name) && !(obj.SAPVB.Data.Set.type)) {
814
+ //Full Update - Replace complete Data Section
815
+ featureCollection.splice(0, featureCollection.length);
816
+ }
817
+ }
818
+
817
819
  }
818
820
 
819
821
  // Get the datatypes
@@ -34,18 +34,28 @@ sap.ui.define([
34
34
  });
35
35
  };
36
36
 
37
- VectorUtils.createSpotElement = (marker) => {
38
- // create a DOM element for the marker (parent div)
37
+ VectorUtils.createSpotElement = (marker, spotid) => {
39
38
  const el = document.createElement('div');
40
-
41
- // Set background image for the marker
42
- var base64decoded = "data:image/png;base64," + marker.properties.base64;
39
+ const base64decoded = "data:image/png;base64," + (marker.properties.base64 || "");
40
+ el.id = '__mapmarker' + spotid++;
43
41
  el.style.backgroundImage = `url(${base64decoded})`;
44
- el.style.width = marker.properties.width;
45
- el.style.height = marker.properties.height;
46
- el.style.backgroundSize = 'cover'; // Ensure image fits
47
- return el;
42
+ el.style.backgroundSize = 'cover';
43
+ el.style.pointerEvents = 'none';
44
+ el.style.display = 'inline-block';
45
+ el.style.transform = 'translate(-50%, -100%)';
46
+
47
+ // load the image to get natural size
48
+ const img = new Image();
49
+ img.src = base64decoded;
50
+ img.onload = () => {
51
+ const scaleParts = (marker.properties.Scale || "1;1;1").split(';').map(Number);
52
+ const [sx, sy] = scaleParts.some(isNaN) ? [1, 1] : [scaleParts[0], scaleParts[1]];
53
+ el.style.width = `${img.naturalWidth * sx}px`;
54
+ el.style.height = `${img.naturalHeight * sy}px`;
55
+ };
56
+ return {spotEl:el, spotId:spotid};
48
57
  };
58
+
49
59
  VectorUtils.isAccepted = (drag, drop) => {
50
60
  var validDrop = drag.some(item => drop.includes(item));
51
61
  return validDrop;
@@ -252,8 +262,43 @@ sap.ui.define([
252
262
  obj.style.color = textColor;
253
263
  obj.style.fontFamily = 'Arial, sans-serif';
254
264
  obj.style.fontSize = '14px';
265
+ obj.style.padding = '2px 6px';
266
+ obj.style.borderRadius = '4px';
267
+ obj.style.whiteSpace = 'pre-wrap';
268
+ obj.style.boxSizing = 'border-box';
269
+ obj.style.textAlign = 'center';
270
+
255
271
  return obj;
256
272
  }
273
+
274
+ VectorUtils.createRouteLabel = (label, labelcolor) => {
275
+ let r, g, b, a;
276
+ const obj = document.createElement('div');
277
+ obj.className = 'route-label';
278
+ obj.textContent = label;
279
+
280
+ if (!labelcolor) {
281
+ [r, g, b, a] = [211, 211, 211, 1];
282
+ } else {
283
+ [r, g, b, a] = VectorUtils.parseRGBAString(labelcolor);
284
+ }
285
+
286
+ const textColor = VectorUtils.getContrastTextColor(r, g, b);
287
+
288
+ obj.style.backgroundColor = `rgba(${r}, ${g}, ${b}, ${a})`;
289
+ obj.style.border = `2px solid rgba(${r}, ${g}, ${b}, ${a})`;
290
+ obj.style.color = textColor;
291
+ obj.style.fontFamily = 'Arial, sans-serif';
292
+ obj.style.fontSize = '14px';
293
+ obj.style.padding = '2px 6px';
294
+ obj.style.borderRadius = '4px';
295
+ obj.style.whiteSpace = 'pre-wrap';
296
+ obj.style.boxSizing = 'border-box';
297
+ obj.style.textAlign = 'center';
298
+
299
+ return obj;
300
+ };
301
+
257
302
  VectorUtils.rgbaToHexAndOpacity = (rgbaString) => {
258
303
  const rgbaRegex = /rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d*\.?\d+)\s*\)/i;
259
304
  const match = rgbaString.match(rgbaRegex);