zoukankan      html  css  js  c++  java
  • cesium 3dtiles模型单体化点击高亮效果

    前言

    cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材。

    cesium官网在线例子

    https://sandcastle.cesium.com/?src=3D+Tiles+Feature+Picking.html

    大概思路如下:

    • 加载3dtiles模型
    var tileset = new Cesium.Cesium3DTileset({
    url: Cesium.IonResource.fromAssetId(75343),
    });
    viewer.scene.primitives.add(tileset);
    • 创建html元素,鼠标移动以及点击模型高亮作用
    // HTML overlay for showing feature name on mouseover
    var nameOverlay = document.createElement("div");
    viewer.container.appendChild(nameOverlay);
    nameOverlay.className = "backdrop";
    nameOverlay.style.display = "none";
    nameOverlay.style.position = "absolute";
    nameOverlay.style.bottom = "0";
    nameOverlay.style.left = "0";
    nameOverlay.style["pointer-events"] = "none";
    nameOverlay.style.padding = "4px";
    nameOverlay.style.backgroundColor = "black";
    • 设置选中要素的样式以及创建选中模型
    // Information about the currently selected feature
    var selected = {
    feature: undefined,
    originalColor: new Cesium.Color(),
    };
     
    // An entity object which will hold info about the currently selected feature for infobox display
    var selectedEntity = new Cesium.Entity();
    • 鼠标响应事件交互
    // 获取默认的左键单击处理程序,用于在左键单击时未拾取要素
    var clickHandler = viewer.screenSpaceEventHandler.getInputAction(
    Cesium.ScreenSpaceEventType.LEFT_CLICK
    );
     
    // 如果支持剪影,则鼠标上方的剪影功能为蓝色,鼠标单击的剪影功能为绿色
    // 如果不支持轮廓,请将特征颜色更改为鼠标悬停时为黄色,单击鼠标时为绿色
    if (
    Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)
    ) {
    // 支持轮廓
    var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteBlue.uniforms.color = Cesium.Color.BLUE;//蓝色
    silhouetteBlue.uniforms.length = 0.01;
    silhouetteBlue.selected = [];
     
    var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteGreen.uniforms.color = Cesium.Color.LIME;
    silhouetteGreen.uniforms.length = 0.01;
    silhouetteGreen.selected = [];
     
    viewer.scene.postProcessStages.add(
    Cesium.PostProcessStageLibrary.createSilhouetteStage([
    silhouetteBlue,
    silhouetteGreen,
    ])
    );
     
    // 在悬停时勾勒出蓝色的轮廓
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(
    movement
    ) {
    // 如果先前高亮显示了某个要素,请撤消该高亮显示
    silhouetteBlue.selected = [];
     
    //点击新要素
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if (!Cesium.defined(pickedFeature)) {
    nameOverlay.style.display = "none";
    return;
    }
     
    //要素被点击,显示它的覆盖内容
    nameOverlay.style.display = "block";
    nameOverlay.style.bottom =
    viewer.canvas.clientHeight - movement.endPosition.y + "px";
    nameOverlay.style.left = movement.endPosition.x + "px";
    var name = pickedFeature.getProperty("BIN");
    nameOverlay.textContent = name;
     
    // 突出显示尚未选定的功能
    if (pickedFeature !== selected.feature) {
    silhouetteBlue.selected = [pickedFeature];
    }
    },
    Cesium.ScreenSpaceEventType.MOUSE_MOVE);
     
    // 在信息框中显示选定内容和元数据
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(
    movement
    ) {
    // 如果先前选择了某个特征,请撤消高亮显示
    silhouetteGreen.selected = [];
     
    // 点击新要素
    var pickedFeature = viewer.scene.pick(movement.position);
    if (!Cesium.defined(pickedFeature)) {
    clickHandler(movement);
    return;
    }
     
    // Select the feature if it's not already selected
    if (silhouetteGreen.selected[0] === pickedFeature) {
    return;
    }
     
    // 保存选定要素的原始颜色
    var highlightedFeature = silhouetteBlue.selected[0];
    if (pickedFeature === highlightedFeature) {
    silhouetteBlue.selected = [];
    }
     
    // 高亮新选择要素
    silhouetteGreen.selected = [pickedFeature];
     
    // 设置要素信息框描述
    var featureName = pickedFeature.getProperty("name");
    selectedEntity.name = featureName;
    selectedEntity.description =
    'Loading <div class="cesium-infoBox-loading"></div>';
    viewer.selectedEntity = selectedEntity;
    selectedEntity.description =
    '<table class="cesium-infoBox-defaultTable"><tbody>' +
    "<tr><th>BIN</th><td>" +
    pickedFeature.getProperty("BIN") +
    "</td></tr>" +
    "<tr><th>DOITT ID</th><td>" +
    pickedFeature.getProperty("DOITT_ID") +
    "</td></tr>" +
    "<tr><th>SOURCE ID</th><td>" +
    pickedFeature.getProperty("SOURCE_ID") +
    "</td></tr>" +
    "</tbody></table>";
    },
    Cesium.ScreenSpaceEventType.LEFT_CLICK);
    } else {
    // 不支持轮廓。相反,更改特征颜色
    // 有关当前突出显示的功能的信息
    var highlighted = {
    feature: undefined,
    originalColor: new Cesium.Color(),
    };
     
    // 鼠标移动显示黄色
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(
    movement
    ) {
    // 如果先前高亮显示了某个要素,请撤消该高亮显示
    if (Cesium.defined(highlighted.feature)) {
    highlighted.feature.color = highlighted.originalColor;
    highlighted.feature = undefined;
    }
    // 点击新要素
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if (!Cesium.defined(pickedFeature)) {
    nameOverlay.style.display = "none";
    return;
    }
    // 要素被点击,显示它的覆盖内容
    nameOverlay.style.display = "block";
    nameOverlay.style.bottom =
    viewer.canvas.clientHeight - movement.endPosition.y + "px";
    nameOverlay.style.left = movement.endPosition.x + "px";
    var name = pickedFeature.getProperty("name");
    if (!Cesium.defined(name)) {
    name = pickedFeature.getProperty("id");
    }
    nameOverlay.textContent = name;
    // Highlight the feature if it's not already selected.
    if (pickedFeature !== selected.feature) {
    highlighted.feature = pickedFeature;
    Cesium.Color.clone(
    pickedFeature.color,
    highlighted.originalColor
    );
    pickedFeature.color = Cesium.Color.YELLOW;
    }
    },
    Cesium.ScreenSpaceEventType.MOUSE_MOVE);
     
    //为所选内容上色并在信息框中显示元数据
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(
    movement
    ) {
    // 如果先前选择了某个特征,请撤消高亮显示
    if (Cesium.defined(selected.feature)) {
    selected.feature.color = selected.originalColor;
    selected.feature = undefined;
    }
    // 点击新要素
    var pickedFeature = viewer.scene.pick(movement.position);
    if (!Cesium.defined(pickedFeature)) {
    clickHandler(movement);
    return;
    }
    // Select the feature if it's not already selected
    if (selected.feature === pickedFeature) {
    return;
    }
    selected.feature = pickedFeature;
    // Save the selected feature's original color
    if (pickedFeature === highlighted.feature) {
    Cesium.Color.clone(
    highlighted.originalColor,
    selected.originalColor
    );
    highlighted.feature = undefined;
    } else {
    Cesium.Color.clone(pickedFeature.color, selected.originalColor);
    }
    // Highlight newly selected feature
    pickedFeature.color = Cesium.Color.LIME;
    // Set feature infobox description
    var featureName = pickedFeature.getProperty("name");
    selectedEntity.name = featureName;
    selectedEntity.description =
    'Loading <div class="cesium-infoBox-loading"></div>';
    viewer.selectedEntity = selectedEntity;
    selectedEntity.description =
    '<table class="cesium-infoBox-defaultTable"><tbody>' +
    "<tr><th>BIN</th><td>" +
    pickedFeature.getProperty("BIN") +
    "</td></tr>" +
    "<tr><th>DOITT ID</th><td>" +
    pickedFeature.getProperty("DOITT_ID") +
    "</td></tr>" +
    "<tr><th>SOURCE ID</th><td>" +
    pickedFeature.getProperty("SOURCE_ID") +
    "</td></tr>" +
    "<tr><th>Longitude</th><td>" +
    pickedFeature.getProperty("longitude") +
    "</td></tr>" +
    "<tr><th>Latitude</th><td>" +
    pickedFeature.getProperty("latitude") +
    "</td></tr>" +
    "<tr><th>Height</th><td>" +
    pickedFeature.getProperty("height") +
    "</td></tr>" +
    "<tr><th>Terrain Height (Ellipsoid)</th><td>" +
    pickedFeature.getProperty("TerrainHeight") +
    "</td></tr>" +
    "</tbody></table>";
    },
    Cesium.ScreenSpaceEventType.LEFT_CLICK);

    其他小专栏例子:3dtiles单体化

    https://xiaozhuanlan.com/topic/3241096587
    具体看上述链接文章,里面有详细的介绍

    本篇文章效果例子:结合geoserver实现3dtiles倾斜模型单体化点击高亮

    实现思路如下:鼠标点击倾斜模型,获取对应的点击坐标点;然后根据pick获取到的坐标点,结合geoserver发布的wfs服务,进行空间查询,匹配对应的geojson数据;最后根据获取到的geojson数据源来绘制显示高亮效果,并且弹出对应气泡窗口。

    效果图:

    • 监听鼠标点击事件:
    this.handler.setInputAction(function (evt) { //单机开始绘制
    var picks = viewer.scene.drillPick(evt.position);
    viewer.scene.render();
    var cartesian;
    var isOn3dtiles = false;
    for (var i = 0; i < picks.length; i++) {
    if ((picks[i] && picks[i].primitive) || picks[i] instanceof Cesium.Cesium3DTileFeature) { //模型上拾取
    isOn3dtiles = true;
    }
    }
    if (isOn3dtiles) {
    cartesian = viewer.scene.pickPosition(evt.position);
    var lnglat = cUtil.cartesianToLnglat(cartesian);//坐标转换
    that.queryWFSData([lnglat]);
    } else {
    console.warn("请到模型上拾取!");
    return;
    }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    queryWFSData: function (lnglats) {
    if (!lnglats || lnglats.length < 1) return;
    var that = this;
    queryWFSData({
    typeName: typeName,
    propertyName: propertyName,
    url: mapUrl,
    queryData: {
    type: '1',
    coors: lnglats
    },
    success: function (data) {
    if (!data.features || data.features.length == 0) {
    console.warn("未查询到相关数据!");
    return;
    }
    that.loadGeojson(data);//查询结果高亮绘制显示
    }
    })
    }
    • 高亮绘制显示:
    loadGeojson: function (data) {
    if (!data) return;
    var that = this;
    Cesium.GeoJsonDataSource.load(data, {
    stroke: Cesium.Color.HOTPINK,
    fill: Cesium.Color.YELLOW.withAlpha(.8),
    clampToGround: true,
    strokeWidth: 3
    }).then(function (dataSource) {
    that.quyerDataSourceArr.push(dataSource);
    viewer.dataSources.add(dataSource);
    var entities = dataSource.entities.values;
    that.bindPopup(entities);
    viewer.flyTo(entities, {
    offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90.0), 100)
    });
    });
    }
    • 气泡窗口显示:
    bindPopup: function (entities) {
    if (!entities || entities.length < 1) return;
    var that = this;
    entities.forEach(function (ent) {
    ent.attr = "loadgeojson";
    var properties = ent._properties;
    var contentStr = "";
    for (var i in properties) {
    var name = ppObj[i];
    var value = properties[i]._value;
    if (name && value) {
    contentStr +=
    `
    <tr>
    <td>${name}</td>
    <td>${value}</td>
    </tr>
    `;
    }
    }
    var content =
    `
    <table style='200px;'>
    ${contentStr}
    </table>
    `;
    //绑定弹窗
    var hierarchy = ent.polygon.hierarchy._value.positions;
    var center = cUtil.getCenterByPositions(hierarchy);
    var lnglat = cUtil.cartesianToLnglat(center);
    var tileH = viewer.scene.sampleHeight(Cesium.Cartographic.fromDegrees(lnglat[0], lnglat[1]));
    var popupCartesian = Cesium.Cartesian3.fromDegrees(lnglat[0], lnglat[1], tileH);
    var popup = new MovePrompt(viewer, {
    type: 2,
    content: content,
    popupCartesian: popupCartesian,
    offset: {
    y: -30
    }
    })
    that.popupArr.push(popup);
    ent.popup = popup;
    });
    }

    更多精彩文章,见下面的cesium小专栏

    GIS之家/Cesium专题 - 小专栏​xiaozhuanlan.com

  • 相关阅读:
    Java (三)APACHE Commons IO 常规操作
    JavaFX FileChooser文件选择器,缓存上一次打开的目录
    JavaFX FileChooser文件选择器、DirectoryChooser目录选择器
    javaFX 在窗口的标题栏显示当前时间,1秒更新一次时间
    Java 实现截屏
    composer安装包的时候触发PHP fatal error,提示允许的内存耗光
    箭头函数
    js中的寄生组合继承
    构造函数的原型
    在string.replace中使用具名组匹配
  • 原文地址:https://www.cnblogs.com/giserhome/p/12821526.html
Copyright © 2011-2022 走看看