VUE3-Cesium(Cesium3DTileStyle-3dtiles样式更改)

目录

1.Cesium3DTileStyle详解

1.1 styling features(样式功能)

1.2 conditions(条件)

1.3  Defining variables(定义变量)

1.4 Meta property(元属性)

2. Expressions-表达式

2.1 Semantics-语义化

2.2 Operators-操作符

2.3 Types-类型

2.3.1 支持类型:

2.3.1 Vector向量:

3. Examples-1设置颜色:

4. Examples-2根据不同条件设置颜色:

4.1 安装dat.GUI插件

4.2 导入dat.gui插件,并实例化:

4.3 设置各种条件,并根据不同条件设置3dtile的不同样式: 

4.4 将不同条件的执行挂在到dat.gui上:

5. Examples-3多条件样式高级设置:

之前的文章讲过通过new Cesium.createOsmBuildings()在Cesium加载Open street map建筑模型,但加载后为白膜,当我们需要对其样式进行更改时,就需要使用Cesium3DTileStyle进行更改。3D 切片样式提供磁贴集要素的简洁声明性样式。样式定义表达式以评估要素的显示,例如(RGB 和半透明性)和属性,通常基于存储在切片的 Batch 表中的要素属性。color show

样式可以应用于不包含要素的切片,在这种情况下,切片将被视为没有属性的隐式单个要素。

虽然可以为切片集创建样式并为其引用属性,但样式独立于切片集,因此任何样式都可以应用于任何切片集。

样式是用JSON定义的,表达式写在JavaScript的一小部分中,为样式进行了扩充。此外,样式语言还提供了一组内置函数来支持常见的数学运算。

下面的示例根据建筑物高度分配颜色。

{
    "show" : "${Area} > 0",
    "color" : {
        "conditions" : [
            ["${Height} < 60", "color('#13293D')"],
            ["${Height} < 120", "color('#1B98E0')"],
            ["true", "color('#E8F1F2', 0.5)"]
        ]
    }
}

1.Cesium3DTileStyle详解

Cesium3DTileStyle应用于Cesium3DTileset的样式,通过new Cesium.Cesium3DTileStyle ( style )创建并使用。官方文档:3D磁贴/规格/样式在主 ·铯GS/3D瓷砖 ·GitHub

1.1 styling features(样式功能)

可用于设置样式特征的视觉属性是属性,其分配的表达式将计算为确定特征是否可见的布尔值,以及属性,其分配的表达式将计算为对象(RGB 和半透明性),后者确定特征的显示颜色。showcolorColor

以下样式为每个要素指定默认的显示和颜色属性:

{
    "show" : "true",
    "color" : "color('#ffffff')"
}

 例如,以下表达式将仅显示 19341 邮政编码中的要素,而不是显示所有要素,可以是依赖于要素属性的表达式:show

{
    "show" : "${ZipCode} === '19341'"
}

 show也可用于更复杂的查询;例如,此处的复合条件和正则表达式仅用于显示其县以 1970 开头且其建成年份大于或等于 1970 的要素:'Chest'

{
    "show" : "(regExp('^Chest').test(${County})) && (${YearBuilt} >= 1970)"
}

 颜色也可以由依赖于要素属性的表达式来定义。例如,以下表达式将温度高于 90 的特征颜色着色为红色,将其他表达式颜色着色为白色:

{
    "color" : "(${Temperature} > 90) ? color('red') : color('white')"
}

 颜色的 alpha 分量定义了要素的不透明度。例如,以下命令根据要素的属性设置要素的 RGB 颜色分量,并使体积大于 100 的要素透明:

{
   "color" : "rgba(${red}, ${green}, ${blue}, (${volume} > 100 ? 0.5 : 1.0))"
}

1.2 conditions(条件)

除了包含表达式的字符串之外,还可以是定义一系列条件的数组(类似于语句)。例如,条件可用于制作具有任何类型的包含/排除间隔的色彩映射表和色带。colorshowif...else

例如,下面的表达式将 ID 属性映射到颜色。条件按顺序计算,因此如果不是 或 ,则条件返回白色。如果未满足任何条件,则要素的颜色将为:${id}'1''2'"true"undefined

{
    "color" : {
        "conditions" : [
            ["${id} === '1'", "color('#FF0000')"],
            ["${id} === '2'", "color('#00FF00')"],
            ["true", "color('#FFFFFF')"]
        ]
    }
}

下一个示例演示如何使用条件,使用具有非独占下限和独占上限的间隔创建色带:

"color" : {
    "conditions" : [
        ["(${Height} >= 1.0)  && (${Height} < 10.0)", "color('#FF00FF')"],
        ["(${Height} >= 10.0) && (${Height} < 30.0)", "color('#FF0000')"],
        ["(${Height} >= 30.0) && (${Height} < 50.0)", "color('#FFFF00')"],
        ["(${Height} >= 50.0) && (${Height} < 70.0)", "color('#00FF00')"],
        ["(${Height} >= 70.0) && (${Height} < 100.0)", "color('#00FFFF')"],
        ["(${Height} >= 100.0)", "color('#0000FF')"]
    ]
}

 由于条件是按顺序计算的,因此可以更简洁地编写以下内容:

"color" : {
    "conditions" : [
        ["(${Height} >= 100.0)", "color('#0000FF')"],
        ["(${Height} >= 70.0)", "color('#00FFFF')"],
        ["(${Height} >= 50.0)", "color('#00FF00')"],
        ["(${Height} >= 30.0)", "color('#FFFF00')"],
        ["(${Height} >= 10.0)", "color('#FF0000')"],
        ["(${Height} >= 1.0)", "color('#FF00FF')"]
    ]
}

1.3  Defining variables(定义变量

 常用的表达式可以存储在具有变量名称作为键的对象中。如果变量引用了已定义表达式的名称,则会将其替换为引用的计算表达式的结果:defines

{
    "defines" : {
        "NewHeight" : "clamp((${Height} - 0.5) / 2.0, 1.0, 255.0)",
        "HeightColor" : "rgb(${Height}, ${Height}, ${Height})"
    },
    "color" : {
        "conditions" : [
            ["(${NewHeight} >= 100.0)", "color('#0000FF') * ${HeightColor}"],
            ["(${NewHeight} >= 50.0)", "color('#00FF00') * ${HeightColor}"],
            ["(${NewHeight} >= 1.0)", "color('#FF0000') * ${HeightColor}"]
        ]
    },
    "show" : "${NewHeight} < 200.0"
}

 定义表达式不能引用其他定义;但是,它可能引用具有相同名称的功能属性。在下面的样式中,高度为 150 的特征将获得红色:

{
    "defines" : {
        "Height" : "${Height}/2.0}",
    },
    "color" : {
        "conditions" : [
            ["(${Height} >= 100.0)", "color('#0000FF')"],
            ["(${Height} >= 1.0)", "color('#FF0000')"]
        ]
    }
}

1.4 Meta property(元属性

可以使用该属性定义要素的非可视属性。例如,下面将 meta 属性设置为包含功能名称的字符串:metadescription

{
    "meta" : {
        "description" : "'Hello, ${featureName}.'"
    }
}

 元属性表达式的计算结果可以是任何类型。例如:

{
    "meta" : {
        "featureColor" : "rgb(${red}, ${green}, ${blue})",
        "featureVolume" : "${height} * ${width} * ${depth}"
    }
}

2. Expressions-表达式

表达式的语言是 JavaScript (EMCAScript 5) 的一小部分,加上本机矢量和正则表达式类型,以及以只读变量形式访问 tileset 功能属性。

2.1 Semantics-语义化

点表示法用于按名称访问属性,例如 。building.name

括号表示法 () 也用于访问属性,例如 building['name']或数组,例如temperatures[1]

调用函数时带有括号 () 和逗号分隔的参数,例如 (isNaN(0.0),color('cyan',0.5))

2.2 Operators-操作符

支持以下运算符,其语义和优先级与JavaScript相同。

一元的:+, -, !
 不支持。~
二元的:||, &&, ===, ! ==, <, >, <=, >=, +, -, *, /, %, =~, ! ~
  不支持。|, ^, &, <<, >>, 和>>>.
三元组: ? :
( )也支持对表达式进行分组,以达到清晰和优先的目的。

逻辑运算符 || 和 && 实现了简化流程;true || expression 不评估右边的表达式,而false && expression不评估右边的表达。

同样,true ? leftExpression : rightExpression只执行左边的表达式,而false ? leftExpression : rightExpression只执行右边的表达式。

2.3 Types-类型

2.3.1 支持类型:

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Array
  • vec2
  • vec3
  • vec4
  • RegExp

 除了vec2、vec3、vec4和RegExp,所有类型的语法和运行时行为都与JavaScript相同。颜色源于CSS3的颜色,并以vec4的形式实现。正则(RegExp)源自JavaScript,在正则部分有描述。

不同类型的示例表达式包括:

  • true,false
  • null
  • undefined
  • 1.0, NaN,Infinity
  • 'Cesium',"Cesium"
  • [0, 1, 2]
  • vec2(1.0, 2.0)
  • vec3(1.0, 2.0, 3.0)
  • vec4(1.0, 2.0, 3.0, 4.0)
  • color('#00FFFF')
  • regExp('^Chest'))

下面主要讲解Vector向量类型(vec2 ,vec3 ,vec4),其他数据类型与JS一致,正则表达也与JS一致:

2.3.1 Vector向量:


styling语言包括2、3和4组成的浮点向量类型:vec2、vec3和vec4。向量构造函数与GLSL共享相同的规则。

1)vec2

vec2(xy : Number) - 用数字初始化每个分量
vec2(x : Number, y : Number) - 使用两个数字进行初始化
vec2(xy : vec2) - 用另一个vec2进行初始化
vec2(xyz : vec3) - 丢弃vec3的第三个分量。
vec2(xyzw : vec4) - 丢弃vec4的第三和第四部分。

2)vec3

vec3(xyz : Number) - 用数字初始化每个分量。
vec3(x : Number, y : Number, z : Number) - 使用三个数字进行初始化
vec3(xyz : vec3) - 用另一个vec3进行初始化
vec3(xyzw : vec4) - 丢弃vec4的第四个分量。
vec3(xy : vec2, z : Number) - 用vec2和数字进行初始化。
vec3(x : Number, yz : vec2) - 使用vec2和数字进行初始化。

3)vec4

vec4(xyzw : Number) - 用数字初始化每个组件
vec4(x : Number, y : Number, z : Number, w : Number) - 使用四个数字进行初始化
vec4(xyzw : vec4) - 用另一个vec4进行初始化
vec4(xy : vec2, z : Number, w : Number) - 用一个vec2和两个数字进行初始化。
vec4(x : Number, yz : vec2, w : Number) - 用一个vec2和两个数字进行初始化。
vec4(x : Number, y : Number, zw : vec2) - 用一个vec2和两个数字进行初始化。
vec4(xyz : vec3, w : Number) - 初始化一个vec3和数字。
vec4(x : Number, yzw : vec3) - 初始化一个vec3和数字。

4)向量的使用
vec2组件可以用

.x, .y
.r, .g
[0], [1]

vec3组件可以用 

.x, .y, .z
.r, .g, .b
[0], [1], [2]

vec4组件可以用 

.x, .y, .z, .w
.r, .g, .b, .a
[0], [1], [2], [3]

与GLSL不同,styling语言不支持swizzling。例如,不支持vec3(1.0).xy。

向量支持以下单项运算符。-, +.

向量支持以下二进制运算符,通过执行分母操作:===,!==,+,-,*,/,和%。例如,vec4(1.0) === vec4(1.0)是真的,因为x、y、z和w分量相等。对于vec2、vec3和vec4,操作符基本上是重载的。

vec2、vec3和vec4有一个toString函数,用于显式(和隐式)转换为格式为'(x,y)'、'(x,y,z)'和'(x,y,z,w)的字符串。

toString() : 字符串
vec2、vec3和vec4没有暴露任何其他函数或原型对象。

3. Examples-1设置颜色:

根据建筑物的不同属性设置颜色,办公楼为红色、商业楼为橙色、居民楼为黄色、0.8透明度,其他为天空蓝、0.8透明度。

// Cesium全球3.5亿做建筑物,数据来源openStreetMap地图
  let tiles3d = new Cesium.createOsmBuildings();
  tiles3d.style = new Cesium.Cesium3DTileStyle({
    color: {
      conditions: [
        ["${feature['building']} === 'office'", "color('red')"],
        ["${feature['building']} === 'commercial'", "color('orange')"],
        ["${feature['building']} === 'residential'", "color('yellow',0.8)"],
        ["true", "color('skyblue',0.8)"],
      ],
    },
  });
  console.log(tiles3d);
  var buildings = viewer.scene.primitives.add(tiles3d);

实现效果:

4. Examples-2根据不同条件设置颜色:

根据不同条件切换颜色:

4.1 安装dat.GUI插件

首先可以根据需求安装一个小的切换插件dat.gui,一个轻量级的图形用户界面,用于在JavaScript中更改变量。dat.GUI 是一个轻量级的图形用户界面库(GUI 组件),使用这个库可以很容易地创建出能够改变代码变量的界面组件。

安装

npm install --save dat.gui

yarn add dat.gui

<script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>

使用

const dat = require('dat.gui');

// ES6:
import * as dat from 'dat.gui';

const gui = new dat.GUI();

api文档

https://github.com/dataarts/dat.gui/blob/master/API.md

4.2 导入dat.gui插件,并实例化:

import * as dat from "dat.gui";//一个轻量级的图形用户界面,用于在JavaScript中更改变量。
const gui = new dat.GUI();

4.3 设置各种条件,并根据不同条件设置3dtile的不同样式: 

条件一:根据建筑物的不同高度设置不同的颜色;

条件二:根据距离中心点距离的远近,由近至远色调逐渐变化;

//点击切换条件并更改颜色
  let params = {
    //根据高度不同设置不同颜色
    heightColor: function () {
      tiles3d.style = new Cesium.Cesium3DTileStyle({
        color: {
          conditions: [
            ["${feature['cesium#estimatedHeight']} > 300", "color('#0000CD')"],
            ["${feature['cesium#estimatedHeight']} > 200", "color('#4169E1')"],
            ["${feature['cesium#estimatedHeight']} > 100", "color('#1E90FF')"],
            ["${feature['cesium#estimatedHeight']} > 50", "color('#00BFFF')"],
            ["${feature['cesium#estimatedHeight']} > 20", "color('#87CEEB')"],
            ["true", "color('#ADD8E6',0.8)"],
          ],
        },
      });
    },
    //根据距离中心点位置距离设置不同颜色
    distanceColor: function () {
      tiles3d.style = new Cesium.Cesium3DTileStyle({
        defines: {
          distance:
          //设置以广州塔为中心判断距离远近
            "distance(vec2(${feature['cesium#longitude']},${feature['cesium#latitude']}),vec2(113.3191, 23.109))",
        },
        color: {
          conditions: [
            ["${distance} < 0.005", "color('#0000CD')"],
            ["${distance} < 0.01", "color('#4169E1')"],
            ["${distance} < 0.015", "color('#1E90FF')"],
            ["${distance} < 0.02", "color('#00BFFF')"],
            ["${distance} < 0.025", "color('#87CEEB')"],
            ["true", "color('#ADD8E6',0.8)"],
          ],
        },
      });
    },
  };

4.4 将不同条件的执行挂在到dat.gui上:

gui.add(params, "heightColor");
gui.add(params, "distanceColor");

实现效果:

1.根据建筑物的不同高度设置不同的颜色;

2. 根据距离中心点距离的远近,由近至远色调逐渐变化;(中心点为广州塔)

5. Examples-3多条件样式高级设置:

设置显示距离中心点位置小于0.04且建筑物特征为公寓的建筑显示,且颜色从近至远(0.01,0.02,0.04为节点)逐渐变浅。

实现代码:

<template>
  <div id="cesiumContainer" ref="cesiumContainer"></div>
</template>

<script setup>
// yarn add cesium
// 将cesium目录下的Build/Cesium4个目录拷贝到public,然后将widgets目录拷贝一份到src下
import * as Cesium from "cesium";
import "./Widgets/widgets.css";
import { onMounted } from "vue";

// 设置cesium token
Cesium.Ion.defaultAccessToken =
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzNkNTE5Zi1mMjY4LTRiN2QtOTRlZC1lOTUyM2NhNDYzNWYiLCJpZCI6NTU0OTYsImlhdCI6MTYyNTAyNjMyOX0.a2PEM4hQGpeuMfeB9-rPp6_Gkm6O-02Dm4apNbv_Dlk";

// 设置cesium静态资源路径
window.CESIUM_BASE_URL = "/";
onMounted(() => {
  var viewer = new Cesium.Viewer("cesiumContainer", {
    // 是否显示信息窗口
    // infoBox: false,

    shouldAnimate: true,
  });

  // 设置沙箱允许使用js
  var iframe = document.getElementsByClassName("cesium-infoBox-iframe")[0];
  iframe.setAttribute(
    "sandbox",
    "allow-same-origin allow-scripts allow-popups allow-forms"
  );
  iframe.setAttribute("src", "");

  // 隐藏logo
  viewer.cesiumWidget.creditContainer.style.display = "none";
  // 添加3D建筑
  let tiles3d = new Cesium.createOsmBuildings();
  const osmBuildings = viewer.scene.primitives.add(tiles3d);
  // 广州塔
  var postion = Cesium.Cartesian3.fromDegrees(
    // 经度
    113.3191,
    // 纬度
    23.109,
    // 高度
    1000
  );
  viewer.camera.flyTo({
    destination: postion,
    duration: 2,
  });

  tiles3d.style = new Cesium.Cesium3DTileStyle({
    defines: {
      distance:
        "distance(vec2(${feature['cesium#longitude']},${feature['cesium#latitude']}),vec2(113.3191,23.109))",//距离计算
    },
    color: {
      conditions: [
        ["${distance} < 0.01", "color('rgba(92,167,186, 1)')"],
        ["${distance} < 0.02", "color('rgba(175,215,237, 1)')"],
        ["${distance} < 0.04", "color('rgba(199,237,233, 1)')"],
        ["true", "color('white')"],
      ],
    },//颜色条件判断
    show: "${distance} < 0.04 && ${feature['building']} === 'apartments'",//并列条件设置
  });
});
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
#cesiumContainer {
  width: 100vw;
  height: 100vh;
}
</style>

实现效果:

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HM-hhxx!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值