Skip to content

Commit cdaaab3

Browse files
authored
Merge pull request #491 from xBimTeam/feature/icons-value-readout
Added value readout component to the icon visualization
2 parents b8abbcc + 22d07d7 commit cdaaab3

File tree

5 files changed

+76
-3
lines changed

5 files changed

+76
-3
lines changed

examples/3d-tracking/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ viewer.addPlugin(icons);
1111
var plane = new InteractiveClippingPlane();
1212
viewer.addPlugin(plane);
1313

14-
const sourceIcon = new Icon("Digger #1", "Tracking digger location along the bridge", null, IconsData.diggerIcon);
14+
const sourceIcon = new Icon("Digger #1", "Tracking digger location along the bridge", null, null, IconsData.diggerIcon);
1515

1616
viewer.on('loaded', args => {
1717
try {

examples/data-visualization/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ const temperatureSource = new HeatmapSource("Temp sensor", products, tempChannel
2323
const humiditySource = new HeatmapSource("Humidity sensor", products, humidityChannelId, 10);
2424
const occupancySource = new HeatmapSource("Occupancy sensor", products, occChannelId, "Occupied");
2525

26-
const sourceIcon = new Icon("Rooms 1 and 2 Sensor", "Temperature sensor", products, IconsData.errorIcon, null, null, null, () => {
26+
const sourceIcon = new Icon("Rooms 1 and 2 Sensor", "Temperature sensor", "22°C", products, IconsData.errorIcon, null, null, null, () => {
2727
viewer.zoomTo(products, 1) });
28+
const otherIcon = new Icon("Temperature Sensor 2", "Temperature sensor", "22°C", [{id: 617, model: 1}], IconsData.successIcon);
2829

2930
let selectedChannel: IHeatmapChannel;
3031
const ranges = [
@@ -71,7 +72,7 @@ viewer.on('loaded', args => {
7172
heatmap.addSource(occupancySource);
7273

7374
icons.addIcon(sourceIcon);
74-
icons.addIcon(new Icon("Temperature Sensor 2", "Temperature sensor", [{id: 617, model: 1}], IconsData.successIcon));
75+
icons.addIcon(otherIcon);
7576
// icons.addIcon(new Icon("Temperature Sensor 3", "Temperature sensor", 1, [447], IconsData.successIcon));
7677

7778
heatmap.renderChannel(selectedChannel.channelId);
@@ -81,21 +82,29 @@ viewer.on('loaded', args => {
8182
temperatureSource.value = getRandomInt(40).toString(); // will work for stringified
8283
heatmap.renderSource(temperatureSource.id);
8384
sourceIcon.description = `Room ${selectedChannel.name}: ${temperatureSource.value}${selectedChannel.unit}`;
85+
sourceIcon.valueReadout = `${temperatureSource.value}${selectedChannel.unit}`;
86+
otherIcon.valueReadout = `22${selectedChannel.unit}`;
8487
}
8588
else if(selectedChannel.channelId === humidityChannelId){
8689
humiditySource.value = getRandomInt(100).toString();
8790
heatmap.renderSource(humiditySource.id);
8891
sourceIcon.description = `Room ${selectedChannel.name}: ${humiditySource.value}${selectedChannel.unit}`;
92+
sourceIcon.valueReadout = `${humiditySource.value}${selectedChannel.unit}`;
93+
otherIcon.valueReadout = `10${selectedChannel.unit}`;
8994
}
9095
else if(selectedChannel.channelId === energyChannelId){
9196
energySource.value = getRandomInt(100).toString();
9297
heatmap.renderSource(energySource.id);
9398
sourceIcon.description = `${selectedChannel.description}: ${energySource.value}${selectedChannel.unit}`;
99+
sourceIcon.valueReadout = `${energySource.value}${selectedChannel.unit}`;
100+
otherIcon.valueReadout = `20${selectedChannel.unit}`;
94101
}
95102
else if(selectedChannel.channelId === occChannelId){
96103
occupancySource.value = occupancySource.value === "Occupied" ? "Vacant" : "Occupied";
97104
heatmap.renderSource(occupancySource.id);
98105
sourceIcon.description = `${selectedChannel.description}: ${occupancySource.value}`;
106+
sourceIcon.valueReadout = `${occupancySource.value}`;
107+
otherIcon.valueReadout = `N/A`;
99108
}
100109

101110
}, 2000);

src/plugins/DataVisualization/Icons/icon.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export class Icon {
1010
private _location: Float32Array;
1111
private _imageData: string;
1212
private _description: string;
13+
private _valueReadout: string;
1314
private _name: string;
1415
private _width: number;
1516
private _height: number;
@@ -24,6 +25,7 @@ export class Icon {
2425
*
2526
* @param {string} name - The name of the icon.
2627
* @param {string} description - A brief description of the icon.
28+
* @param {string | null} valueReadout - A value readout of the icon.
2729
* @param {number} products - The products associated with the icon.
2830
* @param {string} imageData - Base64 encoded image data for the icon.
2931
* @param {Float32Array | null} [location=null] - The XYZ coordinates for the icon location. If not provided, the centroid of the product bounding box is used.
@@ -36,6 +38,7 @@ export class Icon {
3638
constructor(
3739
name: string,
3840
description: string,
41+
valueReadout: string | null,
3942
products: { id: number, model: number }[] | null,
4043
imageData: string | null,
4144
location: Float32Array | null = null,
@@ -48,6 +51,7 @@ export class Icon {
4851
this._location = location;
4952
this._name = name;
5053
this._description = description;
54+
this._valueReadout = valueReadout;
5155
this._width = width;
5256
this._height = height;
5357
this._onIconSelected = onIconSelected;
@@ -126,6 +130,22 @@ export class Icon {
126130
this._description = value;
127131
}
128132

133+
/**
134+
* Gets the value readout of the icon.
135+
* @returns {string} The value readout of the icon.
136+
*/
137+
public get valueReadout(): string {
138+
return this._valueReadout;
139+
}
140+
141+
/**
142+
* Sets the value readout of the icon.
143+
* @param {string} value - The new value readout of the icon.
144+
*/
145+
public set valueReadout(value: string) {
146+
this._valueReadout = value;
147+
}
148+
129149
/**
130150
* Gets the width of the icon.
131151
* @returns {number} The width of the icon.

src/plugins/DataVisualization/Icons/icons-data.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,29 @@ export abstract class IconData{
2020
scale: 1.1;
2121
}
2222
23+
.icon-value-readout {
24+
position: absolute;
25+
background: rgb(255, 255, 255);
26+
color: black;
27+
border-radius: 10px;
28+
padding: 2px 5px;
29+
font-size: 11px;
30+
font-weight: bold;
31+
white-space: nowrap;
32+
top: -18px;
33+
left: 50%;
34+
transform: translateX(-50%);
35+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
36+
pointer-events: none;
37+
z-index: 10;
38+
animation: fadeIn 0.3s ease-in-out;
39+
}
40+
41+
@keyframes fadeIn {
42+
from { opacity: 0; }
43+
to { opacity: 1; }
44+
}
45+
2346
#floatdetails {
2447
display: none;
2548
position: absolute;

src/plugins/DataVisualization/Icons/icons.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,17 @@ export class Icons implements IPlugin {
117117
icon.location = new Float32Array([centerX, centerY, centerZ]);
118118
}
119119
}
120+
121+
const valueDiv = document.createElement('div');
122+
valueDiv.classList.add('icon-value-readout');
123+
valueDiv.id = 'value-' + id;
124+
valueDiv.style.display = 'none'; // Initially hidden
125+
120126
this._instances[id.toString()] = icon;
121127
iconElement.id = "icon" + id;
122128
iconElement.title = (icon.products && icon.products.length)
123129
? `Products ${icon.products.map(p => p.id).join(', ')}` : "";
130+
iconElement.appendChild(valueDiv);
124131
iconElement.appendChild(image);
125132
this._icons.appendChild(iconElement);
126133
this._iconsCount++;
@@ -277,6 +284,20 @@ export class Icons implements IPlugin {
277284
iconLabel.style.display = 'block';
278285
iconLabel.style.left = posLeft + 'px';
279286
iconLabel.style.top = posTop + 'px';
287+
288+
if(icon.valueReadout){
289+
const valueDiv = document.getElementById('value-' + k);
290+
if(valueDiv) {
291+
valueDiv.textContent = icon.valueReadout;
292+
valueDiv.style.display = 'block';
293+
valueDiv.style.top = (iconheight + 5) + 'px';
294+
}
295+
} else {
296+
const valueDiv = document.getElementById('value-' + k);
297+
if(valueDiv) {
298+
valueDiv.style.display = 'none';
299+
}
300+
}
280301
}
281302

282303
} else {

0 commit comments

Comments
 (0)