效果图如下:
关键代码:
/**
* 动态绘制点和线
*/
drawMakerByAnimate () {
const pointsMap = typhoneData.points;
const title = typhoneData.tfid + typhoneData.name;
if (!pointsMap || pointsMap.length === 0) {
return;
}
if (this.markers.length > 0 && this.baiduMap) {
this.markers = [];
this.baiduMap.clearOverlays();
}
// console.log(pointsMap.length);
const linePoints = pointsMap.map((item) => new BMapGL.Point(item.lng, item.lat));
// 添加第一个点的标签
if (linePoints.length > 0) {
const firstPoint = linePoints[0];
const label = new BMapGL.Label(title, {
position: firstPoint,
offset: new BMapGL.Size(20, -5)
});
label.setStyle({
color: '#000',
fontSize: '15px',
backgroundColor: 'white',
border: '1px solid #000',
borderRadius: '3px',
padding: '0 5px',
whiteSpace: 'nowrap'
});
this.baiduMap.addOverlay(label);
this.markers.push(label);
// 绘制折线和点
if (linePoints.length === pointsMap.length) {
this.animateMarkersAndPolyline(pointsMap, linePoints);
}
}
},
animateMarkersAndPolyline (pointsMap, linePoints) {
// 检查 linePoints 是否有数据
if (!linePoints || linePoints.length === 0) {
console.error('数据无效或为空');
return;
}
// 创建并添加 GIF 动画元素
const createTyphoonAnimation = (point) => {
// 确保之前的动画被移除
const existingAnimation = document.getElementById('typhoon-animation');
if (existingAnimation) {
existingAnimation.remove();
}
const img = document.createElement('img');
img.src = typhoonImg; // 动图的路径
img.id = 'typhoon-animation';
img.style.position = 'absolute';
img.style.width = '32px'; // 动图的宽度
img.style.height = '32px'; // 动图的高度
img.style.zIndex = 1000; // 确保在其他标记之上
// 添加到地图容器
document.getElementById('baiduMapLevelTwo').appendChild(img);
// 更新位置
const pixel = this.baiduMap.pointToPixel(point);
img.style.left = `${pixel.x - 16}px`;// 确定图标中心点
img.style.top = `${pixel.y - 16}px`;// 确定图标中心点
};
let index = 0;
const stepDuration = 50; // 每步的时间间隔(毫秒)
// console.log(linePoints);
let newLines = [];
const showNext = () => {
if (index < linePoints.length) {
// console.log(linePoints[index]);
const point = linePoints[index];
newLines.push(point);
const item = pointsMap[index]; // 直接从 pointsMap 获取 item
const powerLevel = Number(item?.power); // 使用可选链确保 item 存在
const fillColor = this.getColorByPowerLevel(powerLevel);
// 创建并添加标记
const marker = new BMapGL.Label('', {
position: point,
offset: new BMapGL.Size(-6, -6)
});
marker.setStyle({
backgroundColor: fillColor,
width: '10px',
height: '10px',
borderRadius: '50%',
border: '1px solid #666',
display: 'block',
boxSizing: 'border-box'
});
marker.addEventListener('mouseover', () => {
this.showPopup(point, item);
});
marker.addEventListener('mouseout', () => {
this.closePopup();
});
this.baiduMap.addOverlay(marker);
this.markers.push(marker);
// 每次创建一个新的 Polyline
if (this.polylines) {
this.baiduMap.removeOverlay(this.polylines);
}
this.polylines = new BMapGL.Polyline(newLines, {
strokeColor: '#0076C9',
strokeWeight: 1,
strokeOpacity: 1
});
this.baiduMap.addOverlay(this.polylines);
// 更新台风图标位置
createTyphoonAnimation(point);
// typhoonMarker.setPosition(point);
index++;
setTimeout(showNext, stepDuration);
}
};
showNext();
},
showPopup (point, item) {
let popupDiv = document.getElementById('typhoon-popup');
// 如果不存在,就创建一个新的
if (!popupDiv) {
popupDiv = document.createElement('div');
popupDiv.id = 'typhoon-popup';
document.body.appendChild(popupDiv);
}
// 更新内容
popupDiv.innerHTML = `
<div style="padding: 10px; background: white; border: 1px solid #ccc;
box-shadow: 0px 0px 5px rgba(0,0,0,0.3); border-radius: 5px;color:#303334;font-size:14px">
<strong>台风时间:</strong> ${item.time}</br>
<strong>中心位置:</strong> ${item.lng}°/${item.lat}°</br>
<strong>风速风力:</strong> ${item.speed}米/秒,
${item.power}级<label style="color:red">(${item.strong})</label></br>
<strong>移速移向:</strong> ${item.movespeed}公里/小时,${item.movedirection}</br>
</div>
`;
// 获取像素坐标
const pixel = this.baiduMap.pointToPixel(point);
popupDiv.style.position = 'absolute'; // 确保是悬浮定位
popupDiv.style.zIndex = '9999';
popupDiv.style.left = `${pixel.x + 20}px`; // 调整以适应悬浮效果
popupDiv.style.top = `${pixel.y - 40}px`;
popupDiv.style.display = 'block';
},
closePopup () {
const popupDiv = document.getElementById('typhoon-popup');
if (popupDiv) {
popupDiv.style.display = 'none';
}
},