Динамическая стилизация

В CesiumJS визуальное представление сцены строится вокруг концепции свойств (Property system), позволяющей задавать параметры объектов не статически, а как функции времени, состояния данных или внешних источников. Это создаёт основу для динамической стилизации, при которой внешний вид геометрии, сущностей и тайлов изменяется в реальном времени без пересоздания сцены.

Ключевой механизм динамической стилизации в CesiumJS — система свойств, реализованная через интерфейс Property. Любой визуальный параметр объекта может быть выражен не фиксированным значением, а функцией, зависящей от времени симуляции JulianDate.

Наиболее часто используемые реализации:

  • ConstantProperty
  • SampledProperty
  • CallbackProperty
  • ColorMaterialProperty
  • CompositeProperty

Пример динамического цвета через CallbackProperty:

const colorProperty = new Cesium.CallbackProperty(function (time, result) {
    const seconds = Cesium.JulianDate.toDate(time).getSeconds();
    const intensity = (Math.sin(seconds * 0.5) + 1.0) / 2.0;

    return Cesium.Color.fromHsl(0.6, 1.0, intensity, result);
}, false);

Такой подход позволяет связать визуальное состояние с любым вычисляемым процессом: временем суток, телеметрией, состоянием датчиков, скоростью объекта.

Динамическое изменение цвета объектов Entity

Сущности (Entity) поддерживают широкий спектр визуальных свойств: цвет, прозрачность, масштаб, высоту экструдирования. Все они могут быть динамическими.

Цвет поверхности:

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(30.5, 50.4),
    ellipse: {
        semiMinorAxis: 20000,
        semiMajorAxis: 30000,
        material: new Cesium.ColorMaterialProperty(
            new Cesium.CallbackProperty(function (time) {
                const t = Cesium.JulianDate.toDate(time).getTime();
                const phase = (t % 5000) / 5000;

                return Cesium.Color.interpolate(
                    Cesium.Color.RED,
                    Cesium.Color.BLUE,
                    phase,
                    new Cesium.Color()
                );
            }, false)
        )
    }
});

Здесь визуальное состояние объекта непрерывно изменяется во времени, без пересоздания геометрии.

Управление прозрачностью и визуальными слоями

Динамическая прозрачность часто используется для визуализации интенсивности процессов, плотности данных или приоритета объектов.

const alphaProperty = new Cesium.CallbackProperty(function (time) {
    const seconds = Cesium.JulianDate.toDate(time).getSeconds();
    return 0.3 + 0.7 * (Math.sin(seconds) * 0.5 + 0.5);
}, false);

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(40, 55),
    point: {
        pixelSize: 20,
        color: Cesium.Color.YELLOW.withAlpha(1.0),
        translucencyByDistance: undefined,
        color: new Cesium.ColorMaterialProperty(
            new Cesium.CallbackProperty(function (time) {
                return Cesium.Color.YELLOW.withAlpha(alphaProperty.getValue(time));
            }, false)
        )
    }
});

Прозрачность может также зависеть от расстояния до камеры, создавая эффект глубины без дополнительной логики рендеринга.

Динамическая стилизация 3D Tiles

Для больших массивов данных основным инструментом является Cesium3DTileStyle. Он позволяет задавать правила стилизации на основе атрибутов объектов.

Простейший стиль:

tileset.style = new Cesium.Cesium3DTileStyle({
    color: "color('white')"
});

Условное окрашивание по свойствам:

tileset.style = new Cesium.Cesium3DTileStyle({
    color: {
        conditions: [
            ["${height} > 200", "color('red')"],
            ["${height} > 100", "color('orange')"],
            ["true", "color('green')"]
        ]
    }
});

Здесь стили применяются на уровне каждого тайла или объекта внутри него, что делает возможной визуализацию миллионов объектов без клиентских циклов.

Использование выражений стиля

Система выражений Cesium позволяет вычислять значения прямо в стиле:

  • арифметика
  • логические операции
  • доступ к свойствам
  • функции цвета

Пример динамического изменения прозрачности:

tileset.style = new Cesium.Cesium3DTileStyle({
    color: "color('blue', ${population} / 1000000)"
});

Такая конструкция масштабирует визуальную интенсивность относительно данных модели.

Пер-вершинная и пер-объектная стилизация

CesiumJS поддерживает два уровня стилизации:

  • per-feature (на объект)
  • per-vertex (на геометрию)

Per-feature применяется через 3D Tiles Style и Entity API.

Per-vertex используется в GeometryInstance:

const instance = new Cesium.GeometryInstance({
    geometry: new Cesium.BoxGeometry({
        vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
        dimensions: new Cesium.Cartesian3(1000, 1000, 1000)
    }),
    attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
            Cesium.Color.fromRandom({ alpha: 1.0 })
        )
    }
});

Такой подход используется при рендеринге больших наборов однотипной геометрии.

Динамика через SampledProperty

Для точных временных рядов применяется SampledProperty, позволяющий задавать значения в дискретные моменты времени.

const position = new Cesium.SampledProperty(Cesium.Cartesian3);

position.addSample(
    Cesium.JulianDate.fromIso8601("2025-01-01T00:00:00Z"),
    Cesium.Cartesian3.fromDegrees(30, 50)
);

position.addSample(
    Cesium.JulianDate.fromIso8601("2025-01-01T01:00:00Z"),
    Cesium.Cartesian3.fromDegrees(31, 51)
);

Хотя данный механизм чаще используется для движения объектов, он также влияет на визуализацию через зависимые свойства (цвет, масштаб, ориентацию).

Связывание визуальных параметров с телеметрией

Динамическая стилизация особенно эффективна при работе с потоковыми данными. Цвет, размер и форма объекта становятся визуальным отражением состояния системы.

const entity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(60, 55),
    point: {
        pixelSize: new Cesium.CallbackProperty(function (time) {
            const value = getSensorValue();
            return 5 + value * 20;
        }, false),
        color: new Cesium.CallbackProperty(function () {
            const value = getSensorValue();
            return value > 0.7
                ? Cesium.Color.RED
                : Cesium.Color.GREEN;
        }, false)
    }
});

Здесь визуальная система превращается в слой представления над потоковыми вычислениями.

Анимация материалов

Материалы в CesiumJS могут обладать внутренней анимацией через шейдерные конструкции и встроенные типы материалов:

  • StripeMaterialProperty
  • CheckerboardMaterialProperty
  • PolylineGlowMaterialProperty

Пример динамической полосатой анимации:

entity.ellipse.material = new Cesium.StripeMaterialProperty({
    evenColor: Cesium.Color.WHITE,
    oddColor: Cesium.Color.BLUE,
    repeat: new Cesium.CallbackProperty(function (time) {
        const seconds = Cesium.JulianDate.toDate(time).getSeconds();
        return 5 + Math.floor(seconds % 10);
    }, false)
});

Материалы такого типа позволяют создавать визуальные эффекты движения без изменения геометрии.

Интеграция динамики с камерой

Стилизация может зависеть от положения камеры, что используется для адаптивной визуализации плотных сцен.

const color = new Cesium.CallbackProperty(function (time, result) {
    const distance = viewer.camera.positionCartographic.height;

    if (distance > 1000000) {
        return Cesium.Color.GRAY.withAlpha(0.3);
    }

    return Cesium.Color.CYAN.withAlpha(1.0);
}, false);

Такой подход снижает визуальную перегрузку при отдалении камеры.

Комбинирование нескольких динамических слоёв

Реальные сцены редко используют один тип динамики. Обычно комбинируются:

  • временные свойства (SampledProperty)
  • вычисляемые свойства (CallbackProperty)
  • стилевые выражения (3D Tiles Style)
  • шейдерные материалы

Пример комбинированного поведения:

  • цвет зависит от данных
  • прозрачность от расстояния
  • размер от времени
  • стиль от атрибутов модели

Это создаёт многослойную систему визуального кодирования информации, где каждый параметр отвечает за отдельное измерение данных.

Ограничения динамической стилизации

Динамические свойства выполняются на стороне клиента и могут влиять на производительность:

  • частые CallbackProperty вызывают нагрузку на главный поток
  • сложные выражения в 3D Tiles Style увеличивают стоимость рендеринга
  • избыточная анимация снижает стабильность FPS

По этой причине предпочтение часто отдаётся SampledProperty и стилям 3D Tiles, которые оптимизированы для массовой обработки объектов.