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" };
代码中会用到的图片