作者:taco
最近有客户要做点聚合的功能,本身cesium自带聚合的方法,而且之前有人写过类似的方法。可以参考这篇文章SuperMap iClient3D for WebGL之点聚合_supermapsupport的博客-CSDN博客nannan 在场景中查询结果通常以标记点(布告板)的形式展现,但是如果标记点较多,不仅会大大增加客户端的渲染时间,让客户端变得很卡,而且会让人产生密集恐惧症(图1)。 .https://blog.csdn.net/supermapsupport/article/details/111868209 但是发现聚合只能用Cesium内定的默认符号,并不能自定义符号。如果使用了本地图片呢?那上面的数字就会消失掉。
var pinimg='./images/location4.png';
cluster.billboard.image = pinimg;
这样并不能满足我们实际的需求,因为我们还需要上面的数字。当然,如果不需要的话也可以直接替换。这样我们就需要查接口是否能带数字替换了。然而PinBuilder却接口表示“我没有”。
都是固定好了的,根本改不了。要不就是有样式改不了字,要不就是有字改不了样式。这时候万能的百度还是给出了答案。有人看了开源cesium的代码,底层是可以改的。实现方式看这篇文章。主要思路就是用Canvas对象重新绘制图片。
/**
* @description: 将图片和文字合成新图标使用(参考Cesium源码)
* @param {*} url:图片地址
* @param {*} label:文字
* @param {*} size:画布大小
* @return {*} 返回canvas
*/
function combineIconAndLabel(url, label, size) {
// 创建画布对象
let canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
let ctx = canvas.getContext("2d");
let promise = new Cesium.Resource.fetchImage(url).then(image => {
// 异常判断
try {
ctx.drawImage(image, 0, 0);
} catch (e) {
console.log(e);
}
// 渲染字体
// font属性设置顺序:font-style, font-variant, font-weight, font-size, line-height, font-family
ctx.fillStyle = Cesium.Color.WHITE.toCssColorString();
ctx.font = 'bold 20px Microsoft YaHei';
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(label, size / 2, size / 2);
return canvas;
});
return promise;
}
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聚合</title>
<link href="../../Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link href="./css/pretty.css" rel="stylesheet">
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script src="./js/config.js"></script>
<script src="./js/tooltip.js"></script>
<script src="./js/spectrum.js"></script>
<script type="text/javascript" src="./SampleData/test.js"></script>
<script type="text/javascript" src="../../Build/Cesium/Cesium.js"></script>
</head>
<body>
<div id="cesiumContainer"></div>
<div class="params-setting-container">
<div class="params-setting-anchor" title="显示/隐藏参数面板"><span class="fui-expand"></span></div>
<div class="params-setting">
<button id="start" class="button black">点选旋转</button>
<button id="sqltest" class="button black">叠加过滤rest</button>
<div class="param-item">
<label for="bloomShow">开启泛光</label>
<input type="checkbox" id="bloomShow">
</div>
<div class="param-item">
<label>亮度阈值</label>
<input type="range" id="bloom-threshold" min="0" max="1" value="1" step="0.1" style="width: 140px">
</div>
<div class="param-item">
<label>泛光强度</label>
<input type="range" id="bloom-intensity" min="0" max="10" value="1" step="0.1" style="width: 140px">
</div>
<div class="param-item">
<label for="hdrShow">开启HDR</label>
<input type="checkbox" id="hdrShow">
</div>
<div class="param-item">
<label for="startNight">开启夜景</label>
<input type="checkbox" id="startNight">
</div>
</div>
</div>
<script>
var viewer = new Cesium.Viewer('cesiumContainer');
viewer.scene.globe.depthTestAgainstTerrain = false;
console.log(ss)
var subtest = ss.sub;
console.log(subtest)
var scene = viewer.scene;
var clusteringlayer = new Cesium.CustomDataSource('clusteringlayer');
viewer.dataSources.add(clusteringlayer);
for (var i = 0; i < subtest.length; i++) {
let x = parseFloat(subtest[i].centerx);
let y = parseFloat(subtest[i].centery);
let name = subtest[i].proname;
console.log(name, x, y)
clusteringlayer.entities.add({
position: Cesium.Cartesian3.fromDegrees(x, y, 100),
billboard: {
image: './images/p.png',
scale: 0.1
}
})
}
var pixelRange = 20;
var minimumClusterSize = 5;
var enabled = true;
//启用集群
clusteringlayer.clustering.enabled = enabled;
//设置扩展屏幕空间边界框的像素范围。
clusteringlayer.clustering.pixelRange = pixelRange;
//可以群集的最小屏幕空间对象
clusteringlayer.clustering.minimumClusterSize = minimumClusterSize;
//将进行实体的广告牌聚类
clusteringlayer.clustering.clusterBillboards = true;
customStyle();
var removeListener;
//自定义地图图钉生成为画布元素
var pinBuilder = new Cesium.PinBuilder();
var aa = null;
function customStyle() {
if (Cesium.defined(removeListener)) {
removeListener();
removeListener = undefined;
} else {
removeListener = clusteringlayer.clustering.clusterEvent.addEventListener(function(clusteredEntities,
cluster) {
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
if (clusteredEntities.length >= 20) {
cluster.billboard.image = combineIconAndLabel('./images/zs_redz.png', clusteredEntities
.length, 64);
cluster.billboard.width = 72;
cluster.billboard.height = 72;
} else if (clusteredEntities.length >= 12) {
cluster.billboard.image = combineIconAndLabel('./images/zs_redz.png', clusteredEntities
.length, 64);
cluster.billboard.width = 56;
cluster.billboard.height = 56;
} else if (clusteredEntities.length >= 8) {
cluster.billboard.image = combineIconAndLabel('./images/zs_redz.png', clusteredEntities
.length, 64);
cluster.billboard.width = 48;
cluster.billboard.height = 48;
} else {
cluster.billboard.image = combineIconAndLabel('./images/zs_redz.png', clusteredEntities
.length, 64);
cluster.billboard.width = 40;
cluster.billboard.height = 40;
}
});
}
}
function combineIconAndLabel(url, label, size) {
// 创建画布对象
let canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
let ctx = canvas.getContext("2d");
let promise = new Cesium.Resource.fetchImage(url).then(image => {
// 异常判断
try {
ctx.drawImage(image, 0, 0);
} catch (e) {
console.log(e);
}
// 渲染字体
// font属性设置顺序:font-style, font-variant, font-weight, font-size, line-height, font-family
ctx.fillStyle = Cesium.Color.WHITE.toCssColorString();
ctx.font = 'bold 20px Microsoft YaHei';
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(label, size / 5, size / 4);
return canvas;
});
return promise;
}
</script>
</body>
</html>
这样我们就完成了自定义样式以及文字
本文含有隐藏内容,请 开通VIP 后查看