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
相关产品推荐
相关产品推荐

