绘制动态立体墙
关键引入文件:
- 第一步:引入框架地图关键文件
- https://mhc.ixiera.com/mhc/main_min.js
- https://mhc.ixiera.com/mhc/Cesium-1.120/Build/Cesium/Cesium.js
- https://mhc.ixiera.com/mhc/Cesium3DTile.js
- 第二步:引入动态立体墙绘制文件
- https://mhc.ixiera.com/mhc/mchmap/DynamicWall/js/DynamicWall.min.js
1. 初始化
wall = new DynamicWall(viewer, options);
2. 参数说明
一、构造函数参数。
| 参数 | 数据类型 | 是否必填 | 说明 |
| viewer | Object | 必填 | Cesium Viewer 实例 |
| options | Object | 选填 | 全局配置参数(详见下方表格) |
二、draw 方法配置参数(也可在构造函数中传入)。
| 参数 | 数据类型 | 是否必填 | 默认值 | 说明 |
| positions | Array | 必填 | - | 墙体底面坐标,格式 [[lon, lat], ...](经纬度数组) |
| height | number | 选填 | 100 | 墙体高度(米) |
| arrowType | string | 选填 | undefined | 箭头类型:'arrow'、'chevron'、'triangle'、'line'、'dot'、'custom',不设置则不显示 |
| arrowDirection | string | 选填 | 'left' | 箭头指向:'left'、'right'、'up'、'down'、'both' |
| arrowSize | number | 选填 | 28 | 箭头尺寸(像素) |
| arrowThickness | number | 选填 | 0.5 | 箭头粗细系数(0~1) |
| arrowGap | number | 选填 | 18 | 箭头间距(像素) |
| flowAxis | string | 选填 | 'horizontal' | 流动方向:'horizontal'(水平)或 'vertical'(垂直) |
| flowSpeed | number | 选填 | 2.0 | 流动速度 |
| flowDirection | string | 选填 | 'forward' | 流动方向:'forward'(正向)或 'backward'(反向)。 水平:正向=向右,反向=向左;垂直:正向=向上,反向=向下 |
| color | string | 选填 | '#ffff00' | 箭头颜色(CSS 颜色字符串) |
| opacity | number | 选填 | 0.9 | 箭头整体透明度(0~1) |
| scanMode | string | 选填 | 'none' | 扫描模式:'none'、'vertical'(垂直线)或 'horizontal'(水平线) |
| scanColor | string | 选填 | '#ff0000' | 扫描线颜色 |
| scanSpeed | number | 选填 | 1.0 | 扫描速度 |
| scanDirection | string | 选填 | 'up' | 扫描方向:垂直时为 'up'/'down',水平时为 'right'/'left' |
| scanWidth | number | 选填 | 0.3 | 扫描线宽度(占画布高度的比例) |
| scanOpacity | number | 选填 | 0.8 | 扫描线透明度 |
| scanGradient | boolean | 选填 | true | 是否启用渐变边缘 |
| borderColor | string | 选填 | '#ffaa00' | 边框颜色 |
| borderWidth | number | 选填 | 2.0 | 边框线宽(像素) |
| borderGlow | number | 选填 | 0.3 | 边框发光强度 |
| showBorder | boolean | 选填 | true | 是否显示边框 |
| textureType | string | 选填 | 'canvas' | 纹理类型:'canvas'(内置箭头)或 'image'(外部图片) |
| imageUrl | string | 选填 | null | 图片地址(DataURL 或 URL) |
| imageRepeat | Object | 选填 | {x:10, y:1} | 水平/垂直重复次数({x: number, y: number}) |
| imageColor | string | 选填 | '#ffffff' | 图片叠加颜色(白色为原色) |
| animationType | string | 选填 | 'flow' | 动画类型:'flow'(流动)或 'pulse'(脉冲闪烁) |
| pulseSpeed | number | 选填 | 1.0 | 脉冲速度 |
| repeatVertical | boolean | 选填 | false | 图片纹理/箭头垂直方向是否多行 |
| verticalCount | number | 选填 | 1 | 垂直行数(仅 repeatVertical: true 时生效) |
| canvasWidth | number | 选填 | 1024 | 内部画布宽度(像素),影响纹理分辨率 |
| canvasHeight | number | 选填 | 128 | 内部画布高度(像素),影响纹理分辨率 |
| backgroundColor | string | 选填 | null | 墙体背景色(CSS 颜色字符串),默认透明 |
| backgroundOpacity | number | 选填 | 0 | 背景透明度(0~1),仅在 backgroundColor 不为空时生效 |
| customDraw | function | 选填 | null | 自定义绘制函数 (ctx, x, y, size, config) => {...} |
| cameraOffset | number | 选填 | 600 | 飞向墙体时的附加距离(米) |
| cameraPitch | number | 选填 | -35 | 相机俯仰角(度) |
三、API 方法
| 方法名 | 参数 | 返回值 | 说明 |
| draw(params) | Object | DynamicWall | 绘制墙体,params 可覆盖任何配置项 |
| update(options) | Object | DynamicWall | 更新墙体配置并重新绘制(保留原 positions) |
| clear() | 无 | DynamicWall | 清除所有墙体实体及边框 |
| toggle(visible) | boolean(可选) | boolean | 切换显示/隐藏,返回当前可见状态 |
| flyTo(options) | Object | DynamicWall | 相机飞向墙体中心,options:{ cameraOffset, cameraPitch, heading, duration } |
| getCenter() | 无 | Cartesian3 | 获取墙体中心点坐标 |
| getBoundingBox() | 无 | BoundingSphere | 获取墙体外接球体 |
| destroy() | 无 | void | 销毁实例,释放资源 |
4. 使用示例
4.1 基础绘制(水平流动箭头)
// 定义墙体底面坐标
const positions = [
[116.3860, 39.9060],
[116.3940, 39.9060],
[116.3940, 39.9140],
[116.3860, 39.9140]
];
// 绘制带箭头的墙体
const wall = new DynamicWall(viewer, {
positions: positions,
height: 120,
arrowType: 'arrow',
arrowDirection: 'left',
color: '#ffff00',
flowSpeed: 2.0,
borderColor: '#ffaa00',
showBorder: true
});
wall.draw();
wall.flyTo();
4.2 垂直流动(向上/向下)
// 向上流动(forward)
wall.draw({
flowAxis: 'vertical',
flowDirection: 'forward',
arrowDirection: 'up',
color: '#00ff88'
});
// 向下流动(backward)
wall.draw({
flowAxis: 'vertical',
flowDirection: 'backward',
arrowDirection: 'down',
color: '#00aaff'
});
4.3 扫描效果(无箭头)
// 只显示扫描线,不显示箭头
wall.draw({
arrowType: undefined, // 不显示箭头
scanMode: 'vertical',
scanColor: '#ff0000',
scanDirection: 'up',
scanSpeed: 0.8,
scanWidth: 0.5,
scanOpacity: 0.9,
borderColor: '#ff0000'
});
4.4 图片纹理无缝流动
// 生成箭头图片 DataURL
const canvas = document.createElement('canvas');
canvas.width = 64; canvas.height = 64;
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#ffff00';
ctx.lineWidth = 8;
ctx.beginPath();
ctx.moveTo(10, 15);
ctx.lineTo(45, 32);
ctx.lineTo(10, 49);
ctx.stroke();
const imageUrl = canvas.toDataURL();
// 应用图片纹理
wall.draw({
textureType: 'image',
imageUrl: imageUrl,
imageRepeat: { x: 20, y: 1 },
flowSpeed: 4.0,
repeatVertical: false, // 仅单行
height: 290
});
4.5 脉冲动画
wall.draw({
arrowType: 'arrow',
arrowDirection: 'both',
animationType: 'pulse',
pulseSpeed: 1.5,
color: '#00ffff'
});
4.6 自定义图案(闪电)
wall.draw({
arrowType: 'custom',
customDraw: function(ctx, x, y, size, config) {
const half = size / 2;
ctx.lineWidth = size * 0.5;
ctx.strokeStyle = ctx.fillStyle;
ctx.beginPath();
ctx.moveTo(x - half*0.3, y - half*0.8);
ctx.lineTo(x + half*0.2, y - half*0.1);
ctx.lineTo(x - half*0.1, y - half*0.1);
ctx.lineTo(x + half*0.3, y + half*0.8);
ctx.stroke();
},
color: '#ffff00'
});
4.7 显示控制
// 显示并飞向墙体
wall.flyTo();
// 隐藏
wall.toggle(false);
// 切换
wall.toggle();
// 获取可见状态
const visible = wall.toggle(); // 返回当前状态
4.8 更新与清除
// 更新配置(保持位置不变)
wall.update({ color: '#ff6600', flowSpeed: 3.0 });
// 完全清除
wall.clear();
// 销毁实例
wall.destroy();
5. 完整代码实例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态立体墙演示</title>
<script src="https://mhc.ixiera.com/mhc/main.js"></script>
<script src="https://mhc.ixiera.com/mhc/Cesium-1.120/Build/Cesium/Cesium.js"></script>
<script src="https://mhc.ixiera.com/mhc/Cesium3DTile.js"></script>
<script src="https://mhc.ixiera.com/mhc/mchmap/DynamicWall/js/DynamicWall.min.js"></script>
<style>
html,body,#cesiumContainer { width:100%; height:100%; margin:0; padding:0; overflow:hidden; }
.btns { position:fixed; top:10px; left:10px; z-index:1000; display:flex; gap:8px; flex-wrap:wrap; }
.btns button { background:#fff; border:1px solid #ccc; border-radius:4px; padding:5px 12px; cursor:pointer; font-size:12px; }
.btns button.active { background:#ffaa00; color:#fff; border-color:#ffaa00; }
.info { position:fixed; bottom:10px; left:10px; z-index:1000; background:rgba(0,0,0,0.8); color:#fff; padding:10px 15px; border-radius:6px; font-size:12px; max-width:400px; }
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<div class="btns">
<button onclick="demoArrow()" class="active">箭头</button>
<button onclick="demoScan()">扫描</button>
<button onclick="demoImage()">图片纹理</button>
<button onclick="demoPulse()">脉冲</button>
<button onclick="toggleShow()">切换显示</button>
<button onclick="clearWall()">清除</button>
</div>
<div class="info" id="info">点击按钮切换效果</div>
<script>
const view3D = MchCesium.init('cesiumContainer', true);
const viewer = MchCesium.viewer;
viewer.scene.globe.depthTestAgainstTerrain = true;
let wall = null;
const positions = [
[116.3860, 39.9060],
[116.3940, 39.9060],
[116.3940, 39.9140],
[116.3860, 39.9140]
];
function demoArrow() {
clearWall();
wall = new DynamicWall(viewer, {
positions: positions,
height: 120,
arrowType: 'arrow',
arrowDirection: 'left',
color: '#ffff00',
flowSpeed: 2.0,
borderColor: '#ffaa00',
showBorder: true
});
wall.draw();
wall.flyTo();
setActive(0);
document.getElementById('info').innerText = '水平流动箭头(←)';
}
function demoScan() {
clearWall();
wall = new DynamicWall(viewer, {
positions: positions,
height: 150,
scanMode: 'vertical',
scanColor: '#ff0000',
scanDirection: 'up',
scanSpeed: 0.8,
scanWidth: 0.5,
scanOpacity: 0.9,
borderColor: '#ff0000',
showBorder: true
});
wall.draw();
wall.flyTo();
setActive(1);
document.getElementById('info').innerText = '红色扫描线(无箭头)';
}
function demoImage() {
clearWall();
const canvas = document.createElement('canvas');
canvas.width = 64; canvas.height = 64;
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#ffff00';
ctx.lineWidth = 8;
ctx.beginPath();
ctx.moveTo(10, 15);
ctx.lineTo(45, 32);
ctx.lineTo(10, 49);
ctx.stroke();
const imageUrl = canvas.toDataURL();
wall = new DynamicWall(viewer, {
positions: positions,
height: 290,
textureType: 'image',
imageUrl: imageUrl,
imageRepeat: { x: 20, y: 1 },
flowSpeed: 4.0,
borderColor: '#ffaa00',
showBorder: false
});
wall.draw();
wall.flyTo();
setActive(2);
document.getElementById('info').innerText = '图片纹理无缝流动';
}
function demoPulse() {
clearWall();
wall = new DynamicWall(viewer, {
positions: positions,
height: 120,
arrowType: 'arrow',
arrowDirection: 'both',
animationType: 'pulse',
pulseSpeed: 1.5,
color: '#00ffff',
borderColor: '#00cccc',
showBorder: true
});
wall.draw();
wall.flyTo();
setActive(3);
document.getElementById('info').innerText = '脉冲闪烁箭头(双向)';
}
function toggleShow() {
if (wall) {
const visible = wall.toggle();
document.getElementById('info').innerText = visible ? '墙体已显示' : '墙体已隐藏';
}
}
function clearWall() {
if (wall) {
wall.clear();
wall = null;
}
}
function setActive(index) {
document.querySelectorAll('.btns button').forEach((btn, i) => {
btn.classList.toggle('active', i === index);
});
}
// 默认加载箭头演示
setTimeout(demoArrow, 500);
</script>
</body>
</html>
6. 效果展示

Demo地址:https://mhc.ixiera.com/mhc/mchmap/DynamicWall/index.html
扫一扫