Styling Entities


One of the most important aspects of rendering your data is control over how it's presented. We've got a Style system that allows you to colour, extrude, and adjust in other ways based on many different properties.

Within this article we'll cover how to manage Styles for Entity Menu Items. These notes do not apply to Tileset Menu Items.


Please refer to the API Reference "Entity Styles" article for a breakdown of settings and record management.

Style records

The most commonly used process is setting up a Style through our Operator app then pointing your Menu Item at the record's ID.

Typescript
Javascript
import { MenuItemCreator } from "bruce-cesium";
import { ObjectUtils, ZoomControl } from "bruce-models";

// If set to "0" then it'll load the default Style for the Entity Type.
// Eg: if an Entity has the Entity Type "Building" then it'll use the Building's default Style.
const someStyleId = 1;

// Let's try render one of our Entity types using this record:
MenuItemCreator.RenderMenuItems({
    viewer: viewer,
    menuItems: [
        {
            // This can be any string ID, just as long as it doesn't clash with other Menu Items.
            // If you're lazy and testing stuff, you can simply use the ID: "1" or similar.
            id: ObjectUtils.UId(),
            // Caption is useful in case a UI panel renders your Menu Item.
            Caption: "Rentals",
            Type: "BruceEntity",
            BruceEntity: {
                "EntityType.ID": "some-entity-type-id"
            },
            CameraZoomSettings: [
                {
                    // Between 0 and 100,000 meters (to the camera) your Entity will be drawn as a point with your Style.
                    MinZoom: 0,
                    MaxZoom: 100000,
                    DisplayType: ZoomControl.EDisplayType.Point,
                    StyleID: someStyleId
                }
            ]
        }
    ]
});

If you'd like to let the user pick a Style from what is available. You can request the information like so:

Typescript
Javascript
import { Style } from "bruce-models";

Style.GetList({}).then((data) => {
    // There are other kinds of Styles so let's ensure we only let the user pick from entity ones.
    const entityStyles = data.styles.filter(x => !x.Type || x.Type == Style.EType.Entity);
    console.log("Entity Styles", entityStyles);

    // Styles have a "Name" property for the user to choose from,
    // then an "ID" property for you to pass to the Menu Item.
});

Programmatic Styles

We of course allow you to avoid having to deal with Style records and define your own programmatically.
We will cover the Style syntax in a separate article. Below is an example of how to use it.

Typescript
Javascript
import { MenuItemCreator } from "bruce-cesium";
import { ObjectUtils, ZoomControl, PathUtils, Calculator } from "bruce-models";

const style = {
    pointStyle: {
        color: [
            // Mapping based on 'rent' attribute.
            {
                value: {
                    // The Wrap utility ensures the path will be readable by the style calculator.
                    // If your attribute is nested, simply pass the path array into the function, eg: ["location", "longitude"].
                    field: PathUtils.Wrap(["rent"]),
                    // The mapping type is a simple mapping of values to colours.
                    // In this case we're looking for two specific rental costs and assigning them colours.
                    values: [
                        {
                            fieldValue: "£200",
                            appliedValue: "rgba(50, 180, 50, 0.8)"
                        },
                        {
                            fieldValue: "£300",
                            appliedValue: "rgba(50, 50, 180, 0.8)"
                        }
                    ]
                },
                type: Calculator.EValueType.Mapping
            },
            // Gradient based on 'location' -> 'longitude' attribute.
            {
                value: {
                    field: PathUtils.Wrap(["location", "longitude"]),
                    // Within this example I know the min and max values of the longitude attribute.
                    // I am making it go from red to white as the points move along the longitude vector.
                    points: [
                        {
                            position: -1.099,
                            color: "rgba(255, 0, 0, 0.8)"
                        },
                        {
                            position: -1.046,
                            color: "rgba(255, 255, 255, 0.8)"
                        }
                    ]
                },
                type: Calculator.EValueType.Gradient
            },
            // Default if no above options resolved into anything.
            {
                value: "rgba(255, 255, 255, 0.4)",
                type: Calculator.EValueType.Color
            }
        ]
    }
};

// Let's take our previous example and swap out some pieces.
MenuItemCreator.RenderMenuItems({
    viewer: viewer,
    menuItems: [
        {
            "id": ObjectUtils.UId(),
            "Caption": "Rentals",
            "Type": "BruceEntity",
            "BruceEntity": {
                "EntityType.ID": "some-entity-type-id"
            },
            CameraZoomSettings: [
                {
                    MinZoom: 0,
                    MaxZoom: 100000,
                    DisplayType: ZoomControl.EDisplayType.Point,
                    // Set this to -1 to use a programmatic Style.
                    StyleID: -1,
                    // Now define a Style JSON.
                    // This will outline a basic point Style with a colour.
                    Style: style
                }
            ]
        }
    ]
});

Changing Styles

Recently we've added the ability to change what Styles are enabled within a Menu Item. That way if your setup is user driven you don't have to re-enable the Menu Item to update your Entities.

Below is a simple example where we change the Style of a Menu Item after 5 seconds. In this case we changed from Style ID 1 to Style ID 2. This will work with programmatic Styles too.

Typescript
Javascript
import { MenuItemCreator, ViewerUtils } from "bruce-cesium";
import { ObjectUtils, ZoomControl } from "bruce-models";

// Let's try render one of our Entity types using this record:
MenuItemCreator.RenderMenuItems({
    viewer: viewer,
    menuItems: [
        {
            // This can be any string ID, just as long as it doesn't clash with other Menu Items.
            // If you're lazy and testing stuff, you can simply use the ID: "1" or similar.
            "id": ObjectUtils.UId(),
            // Caption is useful in case a UI panel renders your Menu Item.
            "Caption": "Rentals",
            "Type": "BruceEntity",
            "BruceEntity": {
                "EntityType.ID": "some-entity-type-id"
            },
            CameraZoomSettings: [
                {
                    // Between 0 and 100,000 meters (to the camera) your Entity will be drawn as a point with your Style.
                    MinZoom: 0,
                    MaxZoom: 100000,
                    DisplayType: ZoomControl.EDisplayType.Point,
                    StyleID: 1
                }
            ]
        }
    ]
}).then((rendered) => {
    const manager = ViewerUtils.GetManager({
        viewer: viewer
    });
    const menuItem = manager.GetEnabledItem(rendered.menuItemIds[0]);

    setTimeout(() => {
        menuItem.renderManager.UpdateSettings({
            zoomControl: [
                {
                    MinZoom: 0,
                    MaxZoom: 100000,
                    DisplayType: ZoomControl.EDisplayType.Point,
                    StyleID: 2
                }
            ],
            // Default is true. It'll run through rendered entities in batches and re-render them.
            queueRerender: true
        });
    }, 5000);
});

If you'd like re-render your Entity in the scene so the Style is refreshed, read through the Entity Interaction documentation.