CESIUM例子学习(十二)——3D Tiles Styling

3D Tiles Styling,这应该是一个使用率最高的例子了吧,因为觉得它的使用场景实现是太多了。它是可以根据Cesium3DTileFeature属性来进行个性化渲染的功能,比如分级渲染,距离渲染、条件显示。这些功能的实现都很简单,根据项目需要,创建一个相应的Cesium3DTileStyle对你,并赋值给Cesium3DTileset即可完成。但前提条件是,你的3D Tiles的属性字段中得有需要字段与值。如何判断是否有相应字段的方法是,在加载完成3dtiles之后,绑定一个点击事件,利用getProperty方法,查看是否有。代码如下:

function addListener () {
    let scene = viewer.scene
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (click) {
        // setColor()
        var pickedFeature = viewer.scene.pick(click.position)
        console.log("pickedFeature=", pickedFeature)
        if (pickedFeature) {
            // selectFeature(pickedFeature)
            getAllProperty(pickedFeature)
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function getAllProperty (feature) {
    var propertyNames = feature.getPropertyNames()
    var length = propertyNames.length
    for (var i = 0; i < length; ++i) {
        var propertyName = propertyNames[i]
        console.log(propertyName + ': ' + feature.getProperty(propertyName))
    }
}

然后就可以在控制台查看属性了,如下图:

CESIUM例子学习(十二)——3D Tiles Styling_第1张图片

我只是测试练习,所以渲染效果就根据这些字段来。需要注意的是代码中属性字段的名称是严格区分大小写的

一、分级渲染

测试中的分级渲染是根据建筑的高度,渲染成不同的颜色。代码如下:

var tileset
function add3dtiles (url) {
    tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url: url
    }))
    tileset.readyPromise.then((tileset) => {
       //后面相应的效果代码都是放这里。
         setColorByHeight()
        viewer.flyTo(tileset)
    })
}
function setColorByHeight () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        color: {
            conditions: [
                ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
                ["${height} >= 200", "rgb(102, 71, 151)"],
                ["${height} >= 100", "rgb(170, 162, 204)"],
                ["${height} >= 50", "rgb(224, 226, 238)"],
                ["${height} >= 25", "rgb(252, 230, 200)"],
                ["${height} >= 10", "rgb(248, 176, 87)"],
                ["${height} >= 5", "rgb(198, 106, 11)"],
                ["true", "rgb(127, 59, 8)"],
            ],
        },
    });
}

还没有能力去看原码,但setColorByHeight函数中创建分级渲染的方法很清楚,"${height}就是获取Cesium3DTileFeature中height属性的值,如果该直大于等300,则赋值该Cesium3DTileFeature颜色为rgba(45, 0, 75,0.5)。其中rgba应该是GLSL中创建颜色的函数。最后一个是["true", "rgb(127, 59, 8)"],表达的意思是上面都设置完了,剩下的都用rgb(127, 59, 8)这个颜色。实现的效果如下图:

CESIUM例子学习(十二)——3D Tiles Styling_第2张图片

二、按距离渲染

按距离渲染是指,Cesium3DTileFeature离某个点距离当作渲染条件进行的渲染。代码如下:

function colorByDistance () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        defines: {
            distance:
                "distance(vec2(${longitude},${latitude}), vec2(-1.291777521, 0.7105706624))",
        },
        color: {
            conditions: [
                ["${distance} > 0.0012", "color('red')"],
                [
                    "${distance} > 0.0008",
                    "mix(color('yellow'), color('red'), (${distance} - 0.008) / 0.0004)",
                ],
                [
                    "${distance} > 0.0004",
                    "mix(color('green'), color('yellow'), (${distance} - 0.0004) / 0.0004)",
                ],
                ["${distance} < 0.00001", "color('white')"],
                [
                    "true",
                    "mix(color('blue'), color('green'), ${distance} / 0.0004)",
                ],
            ],
        },
    });
}

创建Cesium3DTileStyle的代码中可以看到,分成两部份。defines和color,从实现的效果来看,其实就是在defines中定义了一个叫distance的字段,但是字段的值是由其实它字段参与计算来的。计算的表达式是:

 "distance(vec2(${longitude},${latitude}), vec2(-1.291777521, 0.7105706624))"

意思应该是:它调用了一个GLSL的内置函数distance,用原有属性的经纬度来计算它离vec2(-1.291777521, 0.7105706624)这个点的距离,distance的值,值得注意的是:vec2(-1.291777521, 0.7105706624)是弧度,而实例原码是:

 "distance(vec2(radians(${Longitude}), radians(${Latitude})), vec2(-1.291777521, 0.7105706624))"

即调用了GLSL的radians函数,把经纬度转成弧度,但是我的属性数据本来就是弧度,所以不需要再转换

。而在color的计算中,上面定义的distance就与原有的属性一样使用,其中mix是GLSL的内置函数。实现的效果如下图:

CESIUM例子学习(十二)——3D Tiles Styling_第3张图片

三、按条件显示

按条件显示是设置Cesium3DTileStyle可选属性show的显示条件即可,代码如下:

function hideByHeight () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        show: "${height} > 200",
    });
}

代码的意思是只显示height属性大于200的Cesium3DTileFeature进行渲染。

CESIUM例子学习(十二)——3D Tiles Styling_第4张图片

四、点击交互

测试是点击某个Cesium3DTileFeature时,改变Cesium3DTileFeature的颜色。代码如下:

function addListener () {
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (click) {
        // setColor()
        var pickedFeature = viewer.scene.pick(click.position)
        console.log("pickedFeature=", pickedFeature)
        if (pickedFeature) {
            // selectFeature(pickedFeature)
            // getAllProperty(pickedFeature)
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function selectFeature (feature) {
    var selectbuilding = feature.getProperty('id');
    var s = "${id} ===" + selectbuilding
    console.log("s=", s)
    var selectcontent = s;
    var transparentStyle = new Cesium.Cesium3DTileStyle({
        color: {
            conditions: [
                [selectcontent, "rgb(255,255,0)"],
                ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
                ["${height} >= 200", "rgb(102, 71, 151)"],
                ["${height} >= 100", "rgb(170, 162, 204)"],
                ["${height} >= 50", "rgb(224, 226, 238)"],
                ["${height} >= 25", "rgb(252, 230, 200)"],
                ["${height} >= 10", "rgb(248, 176, 87)"],
                ["${height} >= 5", "rgb(198, 106, 11)"],
                ["true", "rgb(127, 59, 8)"],true表示剩余的显示的对象
            ]
        },
    });
    tileset.style = transparentStyle
}

实现效果如下图:

CESIUM例子学习(十二)——3D Tiles Styling_第5张图片

你可能感兴趣的:(cesium,3D,Tiles,Styling)