30 KiB
30 KiB
Ciyon Web3D 应用开发指南
概述
本文档为AI开发3D地图应用提供指导,重点讲解如何基于 cemap.html 进行二次开发,实现资产点击交互和统计图表展示等功能。
技术栈
前端
- 核心引擎: Cesium.js (基于WebGL的3D地球可视化引擎)
- UI框架: 自定义框架 (ciy.js, ciycmp.js)
- 图表库: ECharts (可选,用于统计图表)
数据库
- MySQL
- 主要数据表:
zc_cemap_data- 地图配置数据zc_cemap_bill- 指示牌资源zc_cemap_glb- GLB模型资源
资产管理
资产说明
系统提供以下资产类型,可通过后台管理界面进行管理:
-
GLB模型资源 - 3D建筑、设施等模型
- 管理界面:
glb.html - 数据表:
zc_cemap_glb - 支持路径分类管理
- 管理界面:
-
指示牌资源 - 平面图片、标识牌等
- 管理界面:
bill.html - 数据表:
zc_cemap_bill - 支持路径分类管理
- 管理界面:
-
3D Tile资源 - 实景航拍、大规模3D场景
- 管理界面:
ceeditor.html(地编器) - 可直接在编辑器中添加和配置
- 管理界面:
地图配置
地图配置存储在 zc_cemap_data 表的 mapjson 字段中,包含:
- 地图源设置(天地图、高德、腾讯、百度等)
- 3D Tile列表
- Entity列表(GLB模型、指示牌等)
- 飞行点列表
- 地形、遮罩等设置
核心API - ciyearth4.js
1. 初始化地图
var ce = new ciyearth();
ce.init({
domid: 'ceContainer', // DOM容器ID或DOM对象
personheight: 1.8, // 眼睛到地面高度
timeline: 0, // 1显示时间轴
ion: 'your-ion-token', // Cesium Ion授权token
sunhourmin: '12:12', // 太阳时间
setin: 3, // 1地球飞入, 2中国飞入, 3直接进入
wmts_source: 1, // 地图源: 1默认, 2纯色, 3天地图, 4高德, 5腾讯, 6百度
wmts_style: 1, // 样式: 1卫星, 2卫星(标注), 3矢量
tiles: [], // 3DTile数组
entitys: [], // Entity数组
flys: [] // 快捷定位点数组
});
3. Entity管理
Entity类型
model- 3D模型(GLB/GLTF)billboard- 永正面(始终朝向相机)plane- 墙面(平面贴图)
添加Entity
ce.addentity({
type: 'model', // 类型: model/billboard/plane
name: '建筑名称',
bind: 'building_123', // 资产编号,用于关联业务数据
lng: 116.39, // 经度
lat: 39.9, // 纬度
height: 10, // 高度
url: '/path/to/model.glb', // 模型URL
w: 10, // 宽度(米) - plane/billboard
h: 10, // 高度(米) - plane/billboard
sc: 1 // 缩放比例
});
添加标记
ce.addmarker({
lng: 116.39,
lat: 39.9,
img: '/path/to/icon.png',
width: 20,
height: 27,
autoheight: true
});
4. 相机控制
飞行到指定位置
ce.flyTo({
fd: {x, y, z}, // 目标位置
fo: {h, p, r} // h:heading, p:pitch, r:roll
}, 3); // 时间(秒)
设置相机位置
ce.setView({
fd: {x, y, z},
fo: {h, p, r}
});
获取相机位置
var camera = ce.getView();
// 返回: {fd: {x, y, z}, fo: {h, p, r}}
5. 事件系统
ce.ciyevent = function(type, act, data, data2) {
if (type == 'entity') {
if (act == 'leftclick') {
// 左键点击Entity
var entity = data.entity;
var bindId = entity.ciydata.bind; // 获取资产编号
console.log('点击了资产:', bindId);
// 在这里处理资产点击事件
showAssetInfo(bindId);
}
} else if (type == 'tile') {
if (act == 'leftclick') {
// 左键点击3D Tile
var primitive = data.primitive;
console.log('点击了Tile');
}
} else if (type == 'control') {
if (act == 'op') {
// 控制操作中(飞行/行走)
// data: Cartographic相机位置
updateCameraInfo(data);
}
}
};
6. 飞行/行走模式
// 开启飞行模式
ce.control_fly_open(false); // 飞行
ce.control_fly_open(true); // 行走
// 关闭飞行模式
ce.control_fly_close();
键盘控制:
W- 前进S- 后退A- 左移D- 右移Q- 上升E- 下降Z- 左转X- 右转空格- 跳跃(行走模式)F- 减速R- 加速ESC- 退出飞行模式
7. 地形管理
// 添加地形
ce.add_terrain('url', {
url: 'https://example.com/terrain',
requestVertexNormals: true,
requestWaterMask: true
});
// 获取高度
var height = await ce.getposheight(cartesian3);
var floorHeight = ce.getfloorheight();
地图应用开发
基础页面结构
<!DOCTYPE html>
<html>
<head>
<title>3D地图应用</title>
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<link href="/zces108/widgets.css" rel="stylesheet" type="text/css" />
<style type="text/css">
#ceContainer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
/* 浮动面板样式 */
.float-panel {
position: absolute;
background: rgba(255, 255, 255, 0.95);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 15px;
z-index: 1000;
}
.float-panel.top {
top: 20px;
left: 50%;
transform: translateX(-50%);
}
.float-panel.left {
top: 80px;
left: 20px;
width: 300px;
max-height: 80vh;
overflow-y: auto;
}
.float-panel.right {
top: 80px;
right: 20px;
width: 350px;
max-height: 80vh;
overflow-y: auto;
}
.float-panel.bottom {
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
/* 控制面板 */
.control-panel {
position: absolute;
right: 0;
top: 0;
background: rgba(255, 255, 255, 0.8);
border-radius: 0 0 0 8px;
padding: 10px;
}
/* 飞行点列表 */
.fly-points {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
padding-bottom: 30px;
}
.fly-points > div {
padding: 8px 20px;
background: rgba(255, 255, 255, 0.9);
border: 1px solid #ddd;
border-radius: 20px;
color: #333;
cursor: pointer;
transition: all 0.3s;
}
.fly-points > div:hover {
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.fly-points > div.select {
background: #007aff;
color: #fff;
border-color: #007aff;
}
/* 图表容器 */
.chart-container {
width: 100%;
height: 200px;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="ceContainer"></div>
<!-- 控制面板 -->
<div class="control-panel">
<div class="flex">
<div class="tip flex1" id="cameraTip"></div>
<div class="btn xs def" onclick="ce.control_fly_open(false)">飞行</div>
<div class="btn xs def" onclick="ce.control_fly_open(true)">步行</div>
</div>
</div>
<!-- 飞行点列表 -->
<div class="fly-points" id="flyPoints"></div>
<!-- 左侧资产列表 -->
<div class="float-panel left" id="assetPanel" style="display:none;">
<h3>资产信息</h3>
<div id="assetInfo"></div>
<div id="assetCharts"></div>
</div>
<!-- 右侧统计面板 -->
<div class="float-panel right" id="statPanel">
<h3>统计数据</h3>
<div id="statContent"></div>
</div>
<!-- 加载脚本 -->
<script type="text/javascript" src="/jscss/ciy.js"></script>
<script type="text/javascript" src="/zces108/Cesium.js"></script>
<script type="text/javascript" src="/zces108/ciyearth.min.js"></script>
<script type="text/javascript" src="/zces108/map.min.js"></script>
<script type="text/javascript" src="/jscss/echarts.min.js"></script>
<script type="text/javascript">
'use strict';
var ce = new ciyearth();
var currentAssetId = null;
var statChart = null;
// 初始化地图
function initMap() {
ciyfn.callfunc('init', {}, function (json) {
var mapset = ciyfn.tojson(json.cemap.mapjson);
mapset.domid = 'ceContainer';
ce.init(mapset);
// 渲染飞行点
renderFlyPoints(mapset.flys);
// 初始化统计图表
initStatChart();
});
}
// 渲染飞行点
function renderFlyPoints(flys) {
if (!flys || flys.length === 0) return;
var container = $5('#flyPoints');
for (var i = 0; i < flys.length; i++) {
var html = $5('<div onclick="flyTo(this)">' + flys[i].name + '</div>');
html.attr('data-dat', flys[i].dat);
container.append(html);
}
}
// 飞行到指定点
function flyTo(dom) {
event.stopPropagation();
$5('.fly-points>div').removeClass('select');
$5(dom).addClass('select');
var dat = $5(dom).attr('data-dat');
ce.flyTo(ciyfn.tojson(dat), 3);
}
// 显示资产信息
function showAssetInfo(assetId) {
currentAssetId = assetId;
// 显示左侧面板
$5('#assetPanel').show();
// 获取资产详情
ciyfn.callfunc('getAssetDetail', {id: assetId}, function (json) {
var html = '<div class="asset-detail">';
html += '<p><strong>名称:</strong> ' + json.data.name + '</p>';
html += '<p><strong>类型:</strong> ' + json.data.type + '</p>';
html += '<p><strong>位置:</strong> ' + json.data.location + '</p>';
html += '<p><strong>状态:</strong> ' + json.data.status + '</p>';
html += '</div>';
$5('#assetInfo').html(html);
// 渲染资产相关图表
renderAssetCharts(json.data);
});
}
// 渲染资产图表
function renderAssetCharts(assetData) {
var chartsContainer = $5('#assetCharts');
chartsContainer.html('');
// 示例:渲染趋势图
var chart1 = $5('<div class="chart-container" id="chart1"></div>');
chartsContainer.append(chart1);
var option1 = {
title: { text: '近7天访问量', left: 'center', textStyle: {fontSize: 12} },
xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] },
yAxis: { type: 'value' },
series: [{
data: assetData.visits || [120, 200, 150, 80, 70, 110, 130],
type: 'line',
smooth: true,
areaStyle: { opacity: 0.3 }
}]
};
var chart1Instance = echarts.init(document.getElementById('chart1'));
chart1Instance.setOption(option1);
// 示例:渲染分布图
var chart2 = $5('<div class="chart-container" id="chart2"></div>');
chartsContainer.append(chart2);
var option2 = {
title: { text: '时段分布', left: 'center', textStyle: {fontSize: 12} },
xAxis: { type: 'category', data: ['00-06', '06-12', '12-18', '18-24'] },
yAxis: { type: 'value' },
series: [{
data: assetData.timeDist || [20, 150, 280, 90],
type: 'bar',
itemStyle: { color: '#5470c6' }
}]
};
var chart2Instance = echarts.init(document.getElementById('chart2'));
chart2Instance.setOption(option2);
// 监听窗口大小变化
window.addEventListener('resize', function() {
chart1Instance.resize();
chart2Instance.resize();
});
}
// 初始化统计图表
function initStatChart() {
var container = $5('#statContent');
container.html('<div class="chart-container" id="statChart"></div>');
statChart = echarts.init(document.getElementById('statChart'));
var option = {
title: { text: '区域统计', left: 'center', textStyle: {fontSize: 14} },
tooltip: { trigger: 'axis' },
legend: { bottom: 0 },
xAxis: { type: 'category', data: ['区域A', '区域B', '区域C', '区域D'] },
yAxis: { type: 'value' },
series: [
{ name: '建筑数', type: 'bar', data: [120, 200, 150, 80] },
{ name: '设备数', type: 'bar', data: [220, 182, 191, 234] }
]
};
statChart.setOption(option);
window.addEventListener('resize', function() {
statChart.resize();
});
}
// 更新相机信息
function updateCameraInfo(cartographic) {
var lng = Cesium.Math.toDegrees(cartographic.longitude);
var lat = Cesium.Math.toDegrees(cartographic.latitude);
var html = '经度:' + lng.toFixed(4) + ' 纬度:' + lat.toFixed(4) + ' 海拔:' + cartographic.height.toFixed(1) + '米';
$5('#cameraTip').html(html);
}
// 设置事件回调
ce.ciyevent = function (type, act, data, data2) {
if (type == 'entity') {
if (act == 'leftclick') {
// 点击Entity
var entity = data.entity;
var bindId = entity.ciydata.bind;
if (bindId) {
showAssetInfo(bindId);
}
}
} else if (type == 'control') {
if (act == 'op') {
// 控制操作中
updateCameraInfo(data);
}
}
};
// 页面加载完成后初始化
ciyfn.pageload(function () {
try {
initMap();
} catch (e) {
console.log('init:', e);
}
});
</script>
</body>
</html>
事件交互
Entity点击事件
ce.ciyevent = function(type, act, data, data2) {
if (type == 'entity' && act == 'leftclick') {
var entity = data.entity;
// 获取Entity信息
var entityInfo = {
id: entity.id,
name: entity.name,
type: entity.ciytype,
bind: entity.ciydata.bind, // 资产编号
position: entity.position._value,
customData: entity.ciydata // 自定义数据
};
console.log('点击Entity:', entityInfo);
// 处理点击事件
handleEntityClick(entityInfo);
}
};
Tile点击事件
if (type == 'tile' && act == 'leftclick') {
var primitive = data.primitive;
console.log('点击3D Tile:', primitive);
// 可以通过拾取获取Tile中的具体建筑信息
// 这需要3D Tile数据中包含属性信息
}
自定义点击事件
// 添加自定义点击处理器
var handler = new Cesium.ScreenSpaceEventHandler(ce.viewer.canvas);
handler.setInputAction(function(click) {
var pickedObject = ce.viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
if (pickedObject.id) {
// 点击了Entity
var entity = pickedObject.id;
console.log('Entity:', entity.name, entity.ciydata);
} else if (pickedObject.primitive) {
// 点击了Primitive(如3D Tile)
console.log('Primitive:', pickedObject.primitive);
}
} else {
// 点击了空白处
console.log('点击空白处');
// 可以关闭浮动面板
$5('#assetPanel').hide();
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
浮动面板
创建浮动面板
// 左侧面板 - 资产信息
var leftPanel = document.createElement('div');
leftPanel.className = 'float-panel left';
leftPanel.style.cssText = 'top: 80px; left: 20px; width: 320px;';
leftPanel.innerHTML = '<h3>资产信息</h3><div id="assetContent"></div>';
document.body.appendChild(leftPanel);
// 右侧面板 - 统计图表
var rightPanel = document.createElement('div');
rightPanel.className = 'float-panel right';
rightPanel.style.cssText = 'top: 80px; right: 20px; width: 380px;';
rightPanel.innerHTML = '<h3>统计数据</h3><div id="statContent"></div>';
document.body.appendChild(rightPanel);
// 顶部面板 - 搜索/筛选
var topPanel = document.createElement('div');
topPanel.className = 'float-panel top';
topPanel.innerHTML = '<input type="text" placeholder="搜索资产..." />';
document.body.appendChild(topPanel);
// 底部面板 - 快捷操作
var bottomPanel = document.createElement('div');
bottomPanel.className = 'float-panel bottom';
bottomPanel.innerHTML = '<button onclick="resetView()">重置视角</button>';
document.body.appendChild(bottomPanel);
面板样式
.float-panel {
position: absolute;
background: rgba(255, 255, 255, 0.95);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 15px;
z-index: 1000;
transition: all 0.3s ease;
}
.float-panel.top {
top: 20px;
left: 50%;
transform: translateX(-50%);
}
.float-panel.left {
top: 80px;
left: 20px;
width: 320px;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
.float-panel.right {
top: 80px;
right: 20px;
width: 380px;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
.float-panel.bottom {
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
/* 面板折叠状态 */
.float-panel.collapsed {
transform: scale(0);
opacity: 0;
pointer-events: none;
}
面板显示/隐藏
// 显示面板
function showPanel(selector) {
$5(selector).removeClass('collapsed');
}
// 隐藏面板
function hidePanel(selector) {
$5(selector).addClass('collapsed');
}
// 切换面板
function togglePanel(selector) {
$5(selector).toggleClass('collapsed');
}
统计图表
使用ECharts渲染图表
// 渲染柱状图
function renderBarChart(containerId, data) {
var chart = echarts.init(document.getElementById(containerId));
var option = {
title: { text: data.title || '柱状图', left: 'center', textStyle: {fontSize: 12} },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: data.categories || [] },
yAxis: { type: 'value' },
series: [{
name: data.seriesName || '数值',
type: 'bar',
data: data.values || [],
itemStyle: { color: '#5470c6' }
}]
};
chart.setOption(option);
return chart;
}
// 渲染折线图
function renderLineChart(containerId, data) {
var chart = echarts.init(document.getElementById(containerId));
var option = {
title: { text: data.title || '折线图', left: 'center', textStyle: {fontSize: 12} },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: data.categories || [] },
yAxis: { type: 'value' },
series: [{
name: data.seriesName || '数值',
type: 'line',
data: data.values || [],
smooth: true,
areaStyle: { opacity: 0.3 }
}]
};
chart.setOption(option);
return chart;
}
// 渲染饼图
function renderPieChart(containerId, data) {
var chart = echarts.init(document.getElementById(containerId));
var option = {
title: { text: data.title || '饼图', left: 'center', textStyle: {fontSize: 12} },
tooltip: { trigger: 'item' },
legend: { bottom: 0 },
series: [{
type: 'pie',
radius: '50%',
data: data.values || [],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
};
chart.setOption(option);
return chart;
}
响应式图表
// 监听窗口大小变化
var charts = [];
function addChart(chart) {
charts.push(chart);
}
window.addEventListener('resize', function() {
charts.forEach(function(chart) {
chart.resize();
});
});
完整示例
示例:智慧园区管理
// 资产数据映射
var assetDataMap = {
'building_001': {
name: 'A栋办公楼',
type: '办公楼',
floors: 18,
area: 12000,
occupancy: 85,
status: '正常',
energy: { today: 4500, month: 120000 },
visits: [120, 200, 150, 80, 70, 110, 130],
timeDist: [20, 150, 280, 90]
},
'building_002': {
name: 'B栋研发中心',
type: '研发中心',
floors: 12,
area: 8000,
occupancy: 92,
status: '正常',
energy: { today: 3800, month: 98000 },
visits: [90, 150, 180, 100, 60, 130, 140],
timeDist: [15, 120, 250, 80]
}
};
// 处理Entity点击
function handleEntityClick(entityInfo) {
var assetId = entityInfo.bind;
if (!assetId || !assetDataMap[assetId]) {
console.log('未知资产:', assetId);
return;
}
var asset = assetDataMap[assetId];
// 显示资产信息面板
showAssetPanel(asset);
// 更新统计图表
updateStatCharts(asset);
// 飞行到资产位置
if (entityInfo.position) {
ce.viewer.flyTo(ce.viewer.entities.getById(entityInfo.id), {
offset: new Cesium.HeadingPitchRange(1.57, -0.6, 50)
});
}
}
// 显示资产信息面板
function showAssetPanel(asset) {
var html = '<div class="asset-info">';
html += '<h4>' + asset.name + '</h4>';
html += '<div class="info-grid">';
html += '<div><span>类型:</span>' + asset.type + '</div>';
html += '<div><span>楼层:</span>' + asset.floors + '层</div>';
html += '<div><span>面积:</span>' + asset.area + '㎡</div>';
html += '<div><span>入住率:</span>' + asset.occupancy + '%</div>';
html += '<div><span>状态:</span><span class="status ' + asset.status + '">' + asset.status + '</span></div>';
html += '</div>';
html += '<div class="energy-info">';
html += '<div><span>今日能耗:</span>' + asset.energy.today + ' kWh</div>';
html += '<div><span>本月能耗:</span>' + asset.energy.month + ' kWh</div>';
html += '</div>';
html += '</div>';
$5('#assetContent').html(html);
}
// 更新统计图表
function updateStatCharts(asset) {
// 更新访问量趋势图
var visitsChart = echarts.init(document.getElementById('visitsChart'));
visitsChart.setOption({
series: [{ data: asset.visits }]
});
// 更新时段分布图
var timeDistChart = echarts.init(document.getElementById('timeDistChart'));
timeDistChart.setOption({
series: [{ data: asset.timeDist }]
});
}
// 初始化页面
function initPage() {
// 初始化地图
ce.init({
domid: 'ceContainer',
wmts_source: 4,
wmts_style: 3,
setin: 3,
entitys: [
{
type: 'model',
name: 'A栋办公楼',
bind: 'building_001',
lng: 116.39,
lat: 39.9,
height: 0,
url: '/models/building_a.glb'
},
{
type: 'model',
name: 'B栋研发中心',
bind: 'building_002',
lng: 116.40,
lat: 39.9,
height: 0,
url: '/models/building_b.glb'
}
]
});
// 设置事件回调
ce.ciyevent = function(type, act, data) {
if (type == 'entity' && act == 'leftclick') {
var entity = data.entity;
handleEntityClick({
id: entity.id,
bind: entity.ciydata.bind,
position: entity.position._value
});
}
};
}
// 页面加载完成后执行
ciyfn.pageload(initPage);
最佳实践
1. 性能优化
// 使用requestRenderMode按需渲染
ce.init({
domid: 'ceContainer',
requestRenderMode: true,
maximumRenderTimeChange: Infinity
});
// 距离优化:只加载视野内的Entity
ce.reloadentity(); // 自动优化加载
// 减少Entity数量
// 对于大量相似Entity,考虑使用3D Tile或PrimitiveCollection
2. 事件处理
// 使用节流防止频繁触发
function throttle(func, delay) {
var lastTime = 0;
return function() {
var now = Date.now();
if (now - lastTime >= delay) {
lastTime = now;
func.apply(this, arguments);
}
};
}
// 应用节流
ce.ciyevent = throttle(function(type, act, data) {
// 处理事件
}, 100);
3. 内存管理
// 销毁图表实例
function disposeCharts() {
charts.forEach(function(chart) {
chart.dispose();
});
charts = [];
}
// 页面卸载时清理
window.addEventListener('beforeunload', function() {
disposeCharts();
ce.destroy();
});
4. 响应式设计
// 监听窗口大小变化
window.addEventListener('resize', function() {
// 调整图表大小
charts.forEach(function(chart) {
chart.resize();
});
// 调整面板位置
updatePanelPositions();
});
// 移动端适配
if (ciyfn.inmobile()) {
// 隐藏部分面板
$5('.control-panel').hide();
// 调整面板样式
$5('.float-panel.left').css('width', '80%');
}
常见问题
1. 如何获取点击的Entity详细信息?
ce.ciyevent = function(type, act, data) {
if (type == 'entity' && act == 'leftclick') {
var entity = data.entity;
console.log('Entity ID:', entity.id);
console.log('Entity Name:', entity.name);
console.log('Entity Type:', entity.ciytype);
console.log('Custom Data:', entity.ciydata);
console.log('Position:', entity.position._value);
}
};
2. 如何在点击时高亮显示Entity?
// 使用轮廓高亮
ce.silhouette.selected = [entity];
// 使用颜色高亮
entity.model.color = Cesium.Color.fromCssColorString('#ffff00');
// 重置高亮
ce.silhouette.selected = [];
entity.model.color = Cesium.Color.WHITE;
3. 如何加载大量Entity而不影响性能?
// 分批加载
var batchSize = 100;
var currentIndex = 0;
function loadBatch() {
var batch = entities.slice(currentIndex, currentIndex + batchSize);
batch.forEach(function(entityData) {
ce.addentity(entityData);
});
currentIndex += batchSize;
if (currentIndex < entities.length) {
setTimeout(loadBatch, 100);
}
}
loadBatch();
4. 如何实现图层的显示/隐藏?
// 给Entity添加分组属性
ce.addentity({
type: 'model',
name: '建筑1',
category: 'building', // 分类
// ...
});
// 控制图层显示
function toggleLayer(category, visible) {
for (var id in ce.entitys) {
var entity = ce.entitys[id];
if (entity.ciydata.category === category) {
entity.show = visible;
}
}
}
// 使用
toggleLayer('building', false); // 隐藏建筑层
toggleLayer('building', true); // 显示建筑层
5. 如何实现搜索定位功能?
// 搜索Entity
function searchEntity(keyword) {
for (var id in ce.entitys) {
var entity = ce.entitys[id];
if (entity.name && entity.name.indexOf(keyword) > -1) {
// 找到匹配的Entity
flyToEntity(id);
return;
}
}
}
// 飞行到Entity
function flyToEntity(entityId) {
var entity = ce.entitys[entityId];
ce.viewer.flyTo(entity, {
offset: new Cesium.HeadingPitchRange(1.57, -0.6, 50)
});
// 高亮显示
ce.silhouette.selected = [entity];
}
参考资料
- Cesium官方文档: https://cesium.com/docs/
- Cesium Ion: https://cesium.com/ion/
- ECharts文档: https://echarts.apache.org/zh/index.html
- 开源作者: 众产®
- 官网: http://ciy.cn/code