cesium实现动态创建广告牌
import { globalColorList, globalTextColorList } from "../js/positionTools.js";
/**
* 广告牌设备图标函数类
*/
export default class DeviceMarker {
constructor(arg) {}
/**
* 初始化广告牌
* @param {*} text 文字
* @param {*} iconType 图表类型
* @param {*} warningLevel 预警等级
* @param {*} config 样式属性配置 fontSize文字大小 lineHeight线高
* @param {*} posObj 经纬度高度对象
* @param {*} id 主机或传感器Id
* @param {*} targetData 整个节点的数据信息
* @param {*} deviceType 设备类型,主机或传感器
* @param {*} maxHeight 最大可见高度
*/
_initMarker(
text,
iconType,
warningLevel = 1,
config = { fontSize: 24, lineHeight: 150 },
posObj,
targetData,
deviceType,
maxHeight = 6500
) {
// 如果经纬度为空,则直接跳过
if (!posObj.lng || !posObj.lat) {
return;
}
let deviceImg = new Image();
// 背景图的url
deviceImg.src = `下面的第二张图片`;
deviceImg.crossOrigin = "Anonymous";
deviceImg.onload = () => {
// 获取设备图片属性
var deviceImagWidth = deviceImg.width;
var deviceImagHeight = deviceImg.height;
// 设置画布属性
var radius = 5;
var labelWidth = (config.fontSize + 2) * text.length;
var labelHeight = config.fontSize * 1.5;
let lineImg = new Image();
lineImg.src = "下面的第一张图片";
lineImg.crossOrigin = "Anonymous";
lineImg.onload = () => {
// 确定指标线的最低高度
if (!!!config.lineHeight) {
config.lineHeight = 20; // 最低高度默认为20px
} else if (config.lineHeight < 20) {
config.lineHeight = 20; // 最低高度默认为20px
}
// 获取指示线图片的属性
var lineImageWidth = lineImg.width;
var lineImageHeight = lineImg.height;
var lineHeight = Math.min(lineImageHeight, config.lineHeight);
// 重新计算画布大小
var canvasWidth = Math.max(deviceImagWidth, labelWidth);
canvasWidth = Math.max(canvasWidth, lineImageWidth);
var canvasHeight = deviceImagHeight + labelHeight + lineHeight;
// 创建画布
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// 绘制标签文字
var labelX = (canvasWidth - labelWidth) / 2;
// 设备文字-圆角矩形
var grad = ctx.createLinearGradient(0, 0, 0, labelHeight); // 创建一个渐变色线性对象
grad.addColorStop(0, globalColorList[warningLevel].start); // 定义渐变色颜色(开始)
grad.addColorStop(1, globalColorList[warningLevel].end); // 定义渐变色颜色(结束)
// 设置fillStyle为当前的渐变对象
ctx.fillStyle = grad;
// ctx.shadowColor = "#fff"; // 阴影颜色
// ctx.shadowBlur = shadowBlur; // 阴影的模糊范围
ctx.roundRect(labelX, 0, labelWidth, labelHeight, radius); // 设置圆角矩形
ctx.fill(); // 填充圆角矩形
// 设备文字-字体
ctx.font = "bold " + config.fontSize + "px lion";
ctx.textAlign = "center";
ctx.textBaseline = "top";
ctx.fillStyle = globalTextColorList[warningLevel];
ctx.shadowBlur = 0; //阴影的模糊范围
ctx.fillText(text, canvasWidth / 2, 10);
// 合成设备图标
var deviceImgX = (canvasWidth - deviceImagWidth) / 2;
var deviceImgY = labelHeight;
ctx.drawImage(deviceImg, deviceImgX, deviceImgY, deviceImagWidth, deviceImagHeight);
// 合成指示线
var lineImgHeight = Math.min(config.lineHeight, lineImageHeight);
var lineImgdX = Math.round((canvasWidth - lineImageWidth) / 2);
var lineImgdY = canvasHeight - lineImgHeight;
var lineImgsX = -1;
var lineImgsY = lineImageHeight - lineImgHeight;
var lineImgWidth = lineImageWidth;
ctx.drawImage(
lineImg,
lineImgsX,
lineImgsY,
lineImgWidth,
lineImgHeight,
lineImgdX,
lineImgdY,
lineImgWidth,
lineImgHeight
);
// 动画参数
let curScale = 1.0; // 当前缩放比例
let speed = 1.0; // 初始变化速率(从1倍开始)
let speedDelta = 0.005 * (warningLevel - 1); // 增量变化速率(速度越来越快)
var timestamp = new Date().valueOf(); // 记录动画开始时间戳
let base64 = canvas.toDataURL("image/png");
let position = Cesium.Cartesian3.fromDegrees(Number(posObj.lng), Number(posObj.lat), Number(posObj.height));
let entity = viewer.entities.add({
position: position,
targetData: targetData,
// 设备:host/device
deviceType: deviceType,
show: true,
billboard: {
image: base64,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 是否贴地
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平对齐
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 重直对齐
scaleByDistance: new Cesium.NearFarScalar(0, 1.0, 500, 0.3),
eyeOffset: new Cesium.Cartesian3(0, 0, 0),
scale:
warningLevel == 1
? 1.0
: new Cesium.CallbackProperty(function changeScale(time, result) {
let minScale = 1.0; // 最小缩放比例(默认1.0)
let maxScale = 1.05; // 最大缩放比例
let speedIntreval = 200; // 动画时间间隔(每隔100毫秒变换一次)
var curTimestamp = new Date().valueOf(); // 当次动画时间戳
if (curTimestamp - timestamp > speedIntreval) {
// 每隔100毫秒变换
speed += speedDelta; // 确定变化速率
curScale = speed ** 2; // 计算当前缩放比例(模拟重力加速度,speed相当(1/2)g(t^2)的时间t)
timestamp = curTimestamp; // 记录本次时间戳(用作计算动画时间间隔)
if (curScale >= maxScale) {
speedDelta *= -1; // 超过最大缩放比例,改为缩小
} else if (curScale <= minScale) {
speedDelta *= -1; // 低于最小缩放比例,改为放大
}
}
return curScale;
}, false),
// pixelOffset: new Cesium.Cartesian2(offsetX, offsetY), //设置偏移量
// pixelOffsetScaleByDistance: new Cesium.NearFarScalar(0, 1.0, 200, 0.3) //设置偏移量
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, maxHeight) // 设置最小和最大距离
}
});
globalEntity.push(entity);
};
};
}
// 创建主机和传感器广告牌函数
_createMarker(element, maxHeight, clampToGround) {
if (element.deviceHostList && element.deviceHostList.length > 0) {
element.deviceHostList.forEach(item => {
try {
let hostHeight = 0 == clampToGround ? item.height : 0;
// 主机的情况
this._initMarker(
item.deviceTypeDict,
item.deviceType,
item.warnLevel || 1,
{ fontSize: 24, lineHeight: item.lineHeight || 150 },
{ lng: item.lng, lat: item.lat, height: hostHeight },
item,
"host",
maxHeight - 100
);
item.deviceCollectorList.forEach(collectorItem => {
try {
// 传感器无经纬度高度信息,bimModelComponentList字段中取,bimModelComponentList有为空的情况
if (collectorItem.bimModelComponentList) {
let { lng, lat, height, lineHeight } = collectorItem.bimModelComponentList.find(
i => i.collectorId == collectorItem.id
);
// 如果clampToGround==0,则图标不贴地,否则将绘制贴地图标
height = 0 == clampToGround ? height : 0;
this._initMarker(
collectorItem.collectorTypeName,
collectorItem.deviceType,
collectorItem.warnLevel,
{ fontSize: 24, lineHeight: lineHeight || 150 },
{ lng: lng, lat: lat, height: height },
collectorItem,
"device",
maxHeight - 100
);
}
} catch (err) {
console.log(err);
}
});
} catch (err) {
console.log(err);
}
});
}
}
// 创建设备图标函数函数
createMarker(mointorPointInfo, clampToGround = 0) {
if (mointorPointInfo.children && mointorPointInfo.children.length > 0) {
mointorPointInfo.children.map(item => {
this._createMarker(item, mointorPointInfo.areaHeight, clampToGround);
});
}
}
// 删除设备图标函数函数
deleteMarker() {
// 清除全部实体
viewer.entities.removeAll();
}
}

// 预警颜色常量字段
export const globalColorList = {
5: { start: "#e21615", end: "#850000" },
4: { start: "#fe7600", end: "#a83300" },
3: { start: "#ffe045", end: "#eb8d00" },
2: { start: "#56a2eb", end: "#1756ae" },
1: { start: "#fdfffc", end: "#cbffe4" }
};
// 预警文字颜色常量字段
export const globalTextColorList = {
5: "#fff",
4: "#fff",
3: "#fff",
2: "#fff",
1: "#333"
};
代码中会用到的图片


浙公网安备 33010602011771号