You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript模态框动画与样式问题求助:API请求后效果优化

问题解决方案

针对你遇到的两个问题,以下是具体修复方案和修改后的代码:

问题1:修复进度dot动画不可见的问题

当前代码中dot的位置设置在按钮点击时就执行,而modal要等图片加载完成后才显示,导致动画在用户看到modal前就已结束。解决思路是将dot的动画逻辑移到图片加载完成、modal显示之后执行,同时先重置dot的初始位置,触发CSS transition效果。

问题2:给包含rankNum的文本添加绿色样式

通过找到包含rankNum的rank项的索引,给对应的.txt元素添加预定义的green类即可。


修改后的完整代码

JavaScript代码

let btn = document.querySelector('.btn');
let modal = document.querySelector('.modal');
let wrap = document.querySelector('.wrap');
let photo = document.querySelector('.photo');
let svg = document.querySelector('svg');

let data = [{
  title: "dog",
  age: 10,
  rank: [{
      rankStatus: 'behind'
    },
    {
      rankStatus: 'generally',
      rankNum: '20'
    },
    {
      rankStatus: 'excellent'
    }
  ]
}]

btn.addEventListener('click', function(e) {
  svg.style.display = "block"

  axios.get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      // 移除重复的load事件监听,避免多次触发
      photo.removeEventListener('load', onPhotoLoaded);
      photo.addEventListener('load', onPhotoLoaded);
      // 设置图片源
      photo.src = response.data.message;
    })
    .catch((error) => console.log(error));
})

// 图片加载完成后的处理函数
function onPhotoLoaded() {
  svg.style.display = "none"
  modal.style.display = "flex";

  // 重置dot到初始位置
  let dot = document.getElementById("dot");
  dot.style.left = "0%";
  
  // 强制浏览器重绘,触发transition动画
  void dot.offsetWidth;

  // 计算并设置dot的目标位置
  let rankItem = data[0].rank.find(item => item.rankNum);
  let progress = rankItem.rankNum;
  let dotPosition = (progress / 30) * 100;
  dot.style.left = dotPosition + "%";

  // 更新文本并添加绿色样式
  let txtElements = document.querySelectorAll('.txt');
  // 找到包含rankNum的项的索引
  let targetRankIndex = data[0].rank.findIndex(item => item.rankNum);
  
  data[0].rank.forEach((rankItem, index) => {
    txtElements[index].textContent = rankItem.rankStatus;
    // 给目标文本添加绿色样式,其他文本移除样式
    if (index === targetRankIndex) {
      txtElements[index].classList.add('green');
    } else {
      txtElements[index].classList.remove('green');
    }
  });
}

wrap.addEventListener('click', function(e) {
  e.stopPropagation();
})

modal.addEventListener('click', function() {
  modal.style.display = "none"
})

CSS代码(无需修改)

.modal {
  width: 100%;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  justify-content: center;
  align-items: center;
}

.wrap {
  width: 300px;
  height: 300px;
  padding: 20px;
  background-color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 20px;
  flex-direction: column;
}

.wrap .photo {
  width: 100%;
  height: 200px;
  object-fit: cover;
  margin-bottom: 20px;
}

.wrap #progress-bar-container {
  width: 100%;
  height: 5px;
  background-color: #fff;
  position: relative;
  display: flex;
  flex-wrap: nowrap;
}

.wrap #progress-bar-container .progress-bar {
  width: 33.33%;
  height: 5px;
  background-color: #ccc;
  margin-right: 8px;
  border-radius: 20px;
}

.wrap #progress-bar-container .progress-bar .txt {
  text-align: center;
  color: #ccc;
  margin-top: 20px;
}

#progress-bar-1 {
  background-color: #ddd;
}

#progress-bar-2 {
  background-color: #ddd;
}

#progress-bar-3 {
  background-color: #ddd;
  margin-right: 0;
}

#dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #333;
  position: absolute;
  top: -3px;
  left: 0;
  transition: left 0.2s ease-out;
}

svg {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

svg .load {
  stroke-dasharray: 0 500;
  animation: rot 1s linear infinite;
}

@keyframes rot {
  100% {
    stroke-dasharray: 500 500;
  }
}

.green {
  color: yellowgreen;
}

HTML代码(无需修改)

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js"></script>
<button class='btn'>open</button>

<div class="modal">
  <div class="wrap">
    <img class="photo" src="" alt="photo">
    <div id="progress-bar-container">
      <div class="progress-bar" id="progress-bar-1">
        <p class="txt">1</p>
      </div>
      <div class="progress-bar" id="progress-bar-2">
        <p class="txt">2</p>
      </div>
      <div class="progress-bar" id="progress-bar-3">
        <p class="txt">3</p>
      </div>
      <div id="dot"></div>
    </div>
  </div>
</div>

<!-- load -->
<svg width="240px" height="240px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <circle cx="110" cy="110" r="90" stroke-width="10" stroke="gainsboro" fill="none"></circle>
  <circle cx="110" cy="110" r="90" stroke-width="10" stroke="darkturquoise" fill="none" class="load"></circle>
</svg>

内容的提问来源于stack exchange,提问作者WEI A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:20:47