Camera.flyTo "freeze" when creating multiples new labels

1. A concise explanation of the problem you’re experiencing.

I’m using Camera flyToBoundingSphere to move from a large area to a smaller area.

During the fly if some conditions are met (range, height) new labels are created with the names of the cities, previously retrieved.

The problem is that when new labels with cities names are created, the fly “freeze” for a while. It’s very noticeable and very annoying.

What is strange is that this problem does not seem to appear if I use a default text in place of cities names.

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

function zoomIn() {

boundingSphere.radius = 7000;

viewer.camera.flyToBoundingSphere(boundingSphere, {

duration: 8,

easingFunction: Cesium.EasingFunction.QUADRACTIC_IN_OUT,

});

}

export function drawLabel(position, text, category, collection = null) {

let properties = getPropertiesFromCategory(category)

// if (text.length > 15) text = stringDivider(text, 15);

let entity = viewer.entities.add({

opacity: 1, /// default value at start

minDistance: properties.minDistance,

maxDistance: properties.maxDistance,

fillColor: properties.fillColor,

outlineColor: properties.outlineColor,

position: position,

label: {

text: text, /// HERE IF I USE “TEXT” IN PLACE OF text THERE’S NO FREEZE FURING THE FLY

font: properties.font,

fillColor: new Cesium.CallbackProperty(function () {

return new Cesium.Color(entity.fillColor.x, entity.fillColor.y, entity.fillColor.z, entity.opacity)

}, false),

outlineColor: new Cesium.CallbackProperty(function () {

return new Cesium.Color(entity.outlineColor.x, entity.outlineColor.y, entity.outlineColor.z, entity.opacity)

}, false),

outlineWidth: properties.outlineWidth,

style: properties.style,

verticalOrigin: properties.verticalOrigin,

heightReference: properties.heightReference,

pixelOffset: properties.pixelOffset,

disableDepthTestDistance: properties.disableDepthTestDistance,

}

});

/// register the listener to camerachanged,

/// to update this label opacity

viewer.camera.changed.addEventListener(() => {

let pos = entity.position._value;

let dist = Cesium.Cartesian3.distance(viewer.camera.positionWC,

pos);

/// get multiplier by min-max range

let rangeMult = 1 - Math.inverseLerp(minRange, maxRange,

Cesium.Math.clamp(dist, minRange, maxRange));

/// get multiplier by min-max distance

let distMult = 1 - Math.inverseLerp(entity.minDistance, entity

.maxDistance,

Cesium.Math.clamp(dist, entity.minDistance, entity.maxDistance));

entity.opacity = rangeMult * distMult;

});

if (collection) collection.push(entity);

};

function getPropertiesFromCategory(category) {

let properties = {

font: “300 15px Roboto”,

outlineWidth: 2,

fillColor: new Cesium.Cartesian3(1, 1, 1),

outlineColor: new Cesium.Cartesian3(0, 0, 0),

style: Cesium.LabelStyle.FILL_AND_OUTLINE,

verticalOrigin: Cesium.VerticalOrigin.BOTTOM,

heightReference: Cesium.HeightReference.NONE,

pixelOffset: new Cesium.Cartesian2(0, -5),

disableDepthTestDistance: Number.POSITIVE_INFINITY,

minDistance: 50000,

maxDistance: 800000,

};

switch (category) {

case “A1”:

properties.font = “700 20px Roboto”;

properties.outlineWidth = 2;

properties.minDistance = 800000;

properties.maxDistance = 2000000;

break;

case “A2”:

properties.font = “700 18px Roboto”;

properties.outlineWidth = 2;

// properties.fillColor = new Cesium.Cartesian3(.2, .5, .9);

properties.minDistance = 170000;

properties.maxDistance = 800000;

break;

case “A3”:

properties.font = “500 16px Roboto”;

properties.outlineWidth = 2;

properties.fillColor = new Cesium.Cartesian3(.9, .5, .2);

properties.minDistance = 130000;

properties.maxDistance = 500000;

break;

case “A4”:

properties.font = “500 14px Roboto”;

properties.outlineWidth = 2;

properties.fillColor = new Cesium.Cartesian3(0, 1, 1);

properties.minDistance = 60000;

properties.maxDistance = 100000;

break;

case “A5”:

properties.font = “500 14px Roboto”;

properties.outlineWidth = 2;

// properties.fillColor = new Cesium.Cartesian3(1, 1, 1);

properties.minDistance = 35000;

properties.maxDistance = 75000;

break;

}

return properties;

}

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

To create label entities only when some camera conditions are met

4. The Cesium version you’re using, your operating system and browser.

1.66

What do you mean by the “default text in place of city names”? Do you mean like the Bing layer with labels?

I think one approach here is to create all the labels ahead of time, but set them to be not visible (with show = false) so you can have smoother camera flys at the expense of a longer initial load time. Did distanceDisplayCondition not work for you here?

Thank-you Omar.

  1. For “default text” I mean 'text: “SOMETEXT”, in place of “text: {text}”, the parameter of the function.

  2. I can’t create all labels in one time because I’m loading them from api (Geo-db cities), and the request of cities is limited, so I have to load them on the base of camera range.

  3. I’m using my own function for opacity because I need to change it on the base of pitch and range too, not only distance

Thanks for the additional explanation.

I think what’s happening here is if they all have the same text, those characters get cached, so it doesn’t need to create new textures for new labels. You can confirm this by changing the default “TEXT” to something unique for each label like “TEXT” + String(Math.random()).

If you’re able to put together a minimal Sandcastle example showing the issue, we could open a GitHub issue specifically for optimizing the creation of new labels. It may be possible to do this asychronously so even if it takes a second for hte label to appear, that it won’t cause the camera to freeze.

One thing you can do in your application is limit how many labels you create per-frame. So if you need to create 100 labels, split them up so you only create 10 per frame, for example.