wangjuncheng
2025-05-23 043c56f2e3a3507bdc439b7df7c116ce2eeea173
src/components/menu/TimeLine.vue
@@ -31,7 +31,7 @@
        <div>专题渲染:
          <el-switch v-model="isColorRenderEnabled" @change="handleColorRenderChange" style="margin-top:-3px"
            :disabled="!isPlaying || !isWaterPrimitiveCreated" />
            <!-- active-text="开" inactive-text="关" -->
          <!-- active-text="开" inactive-text="关" -->
        </div>
      </div>
      <div class="timeline-track" ref="timelineTrack" @click="seekToPosition">
@@ -204,44 +204,33 @@
};
// 播放逻辑
const startPlayback = () => {
  clearInterval(playInterval); // 清除之前的定时器
  clearInterval(playInterval);
  // 根据 playbackRate 设置 timeIncrement
  let timeIncrement;
  switch (playbackRate.value) {
    case 1:
      timeIncrement = 900;
      break;
    case 2:
      timeIncrement = 1800;
      break;
    case 4:
      timeIncrement = 3600;
      break;
    case 8:
      timeIncrement = 5600;
      break;
    default:
      timeIncrement = 900; // 默认为1倍速
      break;
  }
  playInterval = setInterval(() => {
    currentTime.value += timeIncrement;
    if (currentTime.value >= duration.value) {
      currentTime.value = duration.value; // 停在最后一帧
    // 找到当前时间对应的索引
    const currentIndex = findClosestTimestampIndex(currentTime.value);
    const nextIndex = currentIndex + 1;
    // 如果已经是最后一个时间点,停止播放
    if (nextIndex >= waterTimestamps.value.length) {
      currentTime.value = duration.value;
      stopPlayback();
      isPlaying.value = false;
      emit("isPlaying", false);
      emit("playbackFinished", true);
      setTimeout(() => {
        mapUtils.delRain();
      }, 3000);
      return;
    }
    updateWeatherByProgress(); // 根据当前进度更新天气
    // 计算播放进度百分比 [0, 1]
    // 更新时间为下一个时间点的时间差(秒)
    const nextTimestamp = waterTimestamps.value[nextIndex];
    const baseTimestamp = waterTimestamps.value[0];
    currentTime.value = (nextTimestamp - baseTimestamp) / 1000;
    // 触发更新
    updateWeatherByProgress();
    const progress = currentTime.value / duration.value;
    emit("timeUpdate", progress * 100); // 百分比上报
  }, 1000); // 固定每秒执行一次,也可以使用动态间隔(可选)
    emit("timeUpdate", progress * 100);
  }, 1000 / playbackRate.value); // 根据播放速率调整间隔
};
// 降雨变化部分
// 降雨数据相关变量
@@ -306,7 +295,7 @@
    size: 0.7,
    speed: 40,
    density: 35,
    color: '#ADD8E6'
    color: '#ADD8E6'
  },
  {
    name: '大雨',
@@ -324,7 +313,7 @@
    size: 1.3,
    speed: 90,
    density: 80,
    color: '#ADD8E6'
    color: '#ADD8E6'
  },
  {
    name: '大暴雨',
@@ -396,16 +385,36 @@
  clearInterval(playInterval);
};
const skipForward = () =>
  (currentTime.value = Math.min(currentTime.value + 1, duration.value)); // 向前跳转1秒
const skipForward = () => {
  if (waterTimestamps.value.length === 0) return;
  const currentIndex = findClosestTimestampIndex(currentTime.value);
  const nextIndex = currentIndex + 1;
  if (nextIndex >= waterTimestamps.value.length) {
    return;
  }
  const baseTimestamp = waterTimestamps.value[0];
  currentTime.value = (waterTimestamps.value[nextIndex] - baseTimestamp) / 1000;
  setTimeForWaterSimulation(nextIndex);
  if (!isPlaying.value) pauseWaterSimulation();
};
const skipBackward = () =>
  (currentTime.value = Math.max(currentTime.value - 1, 0)); // 向后跳转1秒
const skipBackward = () => {
  if (waterTimestamps.value.length === 0) return;
  const currentIndex = findClosestTimestampIndex(currentTime.value);
  const prevIndex = currentIndex - 1;
  if (prevIndex < 0) {
    return;
  }
  const baseTimestamp = waterTimestamps.value[0];
  currentTime.value = (waterTimestamps.value[prevIndex] - baseTimestamp) / 1000;
  setTimeForWaterSimulation(prevIndex);
  if (!isPlaying.value) pauseWaterSimulation();
};
const toggleSpeedMenu = () => (showSpeedMenu.value = !showSpeedMenu.value);
// 设置播放速率
const setPlaybackRate = (rate) => {
  isColorRenderEnabled.value = false
  playbackRate.value = rate;
  showSpeedMenu.value = false;
  // 停止当前播放
@@ -433,49 +442,38 @@
};
// 时间轴跳转
const seekToPosition = (event) => {
  // 检查是否已经创建了水体模拟层
  if (!isWaterPrimitiveCreated.value) {
    ElMessage({
      message: "请先启动水体模拟后再进行时间轴跳转。",
      type: "warning",
    });
    return; // 阻止后续逻辑执行
    ElMessage.warning("请先启动水体模拟后再进行时间轴跳转。");
    return;
  }
  const rect = timelineTrack.value.getBoundingClientRect();
  const percentage = (event.clientX - rect.left) / rect.width;
  // 计算当前点击位置对应的时间值
  currentTime.value = Math.round(percentage * duration.value);
  emit("timeUpdate", progressPercentage.value);
  if (waterTimestamps.value.length > 0) {
    // 找到最接近的时间戳索引
    const closestIndex = findClosestTimestampIndex(currentTime.value);
    console.log(
      "Clicked timestamp index:",
      closestIndex,
      "Time:",
      dayjs(waterTimestamps.value[closestIndex]).format("YYYY-MM-DD HH:mm:ss")
    );
    // 调用跳转接口,传递索引值
    console.log(closestIndex,'最近的索引值');
    setTimeForWaterSimulation(closestIndex);
  const targetTime = Math.round(percentage * duration.value);
    // 如果当前是暂停状态,调用 pauseWaterSimulation
    if (!isPlaying.value) {
      pauseWaterSimulation();
    }
  }
  // 直接找到最近的 timestamp 索引
  const closestIndex = findClosestTimestampIndex(targetTime);
  const baseTimestamp = waterTimestamps.value[0];
  currentTime.value = (waterTimestamps.value[closestIndex] - baseTimestamp) / 1000;
  // 更新水体模拟时间
  setTimeForWaterSimulation(closestIndex);
  if (!isPlaying.value) pauseWaterSimulation();
};
// 辅助函数:找到最接近的时间戳索引
function findClosestTimestampIndex(currentTimeValue) {
  if (waterTimestamps.value.length === 0) return 0;
  // 计算当前时间对应的毫秒时间戳
  const baseTime = waterTimestamps.value[0];
  const currentTimestamp = baseTime + currentTimeValue * 1000;
  // 找到最接近的 timestamp 索引
  let closestIndex = 0;
  let minDiff = Infinity;
  waterTimestamps.value.forEach((timestamp, index) => {
    const diff = Math.abs(
      dayjs(timestamp).diff(dayjs(waterTimestamps.value[0]), "second") -
      currentTimeValue
    );
    const diff = Math.abs(timestamp - currentTimestamp);
    if (diff < minDiff) {
      minDiff = diff;
      closestIndex = index;
@@ -539,6 +537,7 @@
    getRainfallData()
    // 根据layer.json去获取时间轴信息
    const { waterTimestamps: timestamps } = await fetchWaterSimulationData(serviceInfo);
    // 现在是按照总共有多少个点来渲染时间轴
    if (timestamps) {
      waterTimestamps.value = timestamps;
      updateTimelineRange();
@@ -556,22 +555,14 @@
    });
  }
});
// 根据返回数据的个数去渲染时间轴
function updateTimelineRange() {
  if (waterTimestamps.value.length > 0) {
    const [first, last] = [
      waterTimestamps.value[0],
      waterTimestamps.value.at(-1),
    ];
    props.waterSimulateParams.date = [
      dayjs(first).toISOString(),
      dayjs(last).toISOString(),
    ];
    duration.value = dayjs(last).diff(dayjs(first), "second");
    // console.log("Updated timeline range:", {
    //   ...props.waterSimulateParams,
    //   duration: duration.value,
    // });
    duration.value = (last - first) / 1000; // 毫秒转秒
  }
}