模态框内滑动事件监听器无法更新图片问题求助
问题
我做了一个带图片模态框的网页,点击图片能在模态框内打开,点击「上一张」「下一张」按钮切换图片都正常。但给移动端添加滑动手势功能时出现问题:已添加对应的事件监听器,逻辑为右滑触发上一张按钮点击、左滑触发下一张按钮点击,检查发现modalImg.src确实已更新,但页面上的图片并未发生变化。
初始化代码
// Get the modal var modal = document.getElementById(modal); // Get the image and insert it inside the modal - use its "alt" text as a caption var img = document.getElementById(img_id); var modalImg = document.getElementById("work-img"); var captionText = document.getElementById(caption); var images = document.getElementsByTagName('img'); var srcList = []; var altList = []; for(var i = 0; i < images.length; i++) { if (images[i].src.toString().includes('paintings')) { srcList.push(images[i].src); altList.push(images[i].alt); } }
按钮及相关函数代码
function updateImage(img_src) { //document.write(modalImg.src, captionText.innerHTML); modalImg.src = img_src; captionText.innerHTML = altList[srcList.indexOf(index)] //img = modalImg.src //document.write(modalImg.src, captionText.innerHTML); } img.onclick = function(){ modal.style.display = "block"; modalImg.src = this.src; captionText.innerHTML = this.alt; /* disable scrolling */ document.documentElement.style.overflow = 'hidden'; document.body.scroll = "no"; } // Get the <span> element that closes the modal var close = document.getElementsByClassName("close")[0]; // When the user clicks on <span> (x), close the modal close.onclick = function() { modal.style.display = "none"; /* enable scrolling */ document.documentElement.style.overflow = 'scroll'; document.body.scroll = "yes"; } // Get the <span> element that opens image full-screen var fullscreen = document.getElementsByClassName("fullscreen-button")[0]; // When the user clicks on <span> (x), close the modal fullscreen.onclick = function() { //Use the specification method before using prefixed versions if (modalImg.requestFullscreen) { modalImg.requestFullscreen(); } else if (modalImg.webkitRequestFullscreen) { /* Safari */ modalImg.webkitRequestFullscreen(); } else if (modalImg.msRequestFullscreen) { /* IE11 */ modalImg.msRequestFullscreen(); } } // click image to open in fullscreen modalImg.onclick = function(){ fullscreen.click(); } // Get the <span> element that goes to the next image var next = document.getElementsByClassName("next")[0]; next.onclick = function() { this_img_index = srcList.indexOf(modalImg.src); if (this_img_index == srcList.length-1){ next_img = srcList[0]; } else { next_img = srcList[this_img_index+1]; } updateImage(next_img); } // Get the <span> element that goes to the previous image var prev = document.getElementsByClassName("prev")[0]; prev.onclick = function() { this_img_index = srcList.indexOf(modalImg.src); if (this_img_index == 0){ prev_img = srcList[srcList.length-1]; } else { prev_img = srcList[this_img_index-1]; } //modalImg.src = prev_img; //captionText.innerHTML = altList[srcList.indexOf(prev_img)]; updateImage(prev_img); } // Get the input field var input = document.getElementById("myInput"); document.onkeydown = checkKey; function checkKey(e) { e = e || window.event; // if (e.keyCode == '37') { // left arrow prev.click(); } else if (e.keyCode == '39') { // right arrow next.click(); } else if (e.keyCode == '27') { //escape close.click(); } }
触摸事件监听器代码
var touchStartX; var touchEndX; const minSwipeDistance = 50; // Minimum swipe distance threshold // calculate starting point function handleTouchStart(event) { touchStartX = event.touches[0].clientX; } // calculate ending point function handleTouchMove(event) { touchEndX = event.touches[0].clientX; } function handleTouchEnd() { const swipeDistance = touchStartX - touchEndX; if (swipeDistance < -minSwipeDistance) { // Swipe to previous prev.click(); } else if (swipeDistance > minSwipeDistance){ // Swipe to next var next = document.getElementsByClassName("next")[0]; next.click(); //document.write(modalImg.src); //captionText.innerHTML = altList[srcList.indexOf(index)]; //document.write(modalImg.src); } } // Attach touch event listeners to the image element modal.addEventListener('touchstart', function handleTouchStart(event) { touchStartX = event.touches[0].clientX; }); modal.addEventListener('touchmove', function handleTouchMove(event) { touchEndX = event.touches[0].clientX; }); modal.addEventListener('touchend', function(){ handleTouchEnd(); }); }
问题排查与修复
1. 修复updateImage函数的逻辑错误
函数中altList[srcList.indexOf(index)]的index是未定义变量,导致控制台报错,可能中断图片渲染逻辑。修改为:
function updateImage(img_src) { modalImg.src = img_src; const imgIndex = srcList.indexOf(img_src); captionText.innerHTML = altList[imgIndex]; }
2. 移除触摸事件中重复获取元素的冗余代码
handleTouchEnd中无需重新获取next元素,直接使用全局已定义的变量即可:
function handleTouchEnd() { const swipeDistance = touchStartX - touchEndX; if (swipeDistance < -minSwipeDistance) { prev.click(); } else if (swipeDistance > minSwipeDistance){ next.click(); } }
3. 阻止触摸滑动的默认行为
移动端触摸时浏览器可能触发默认滚动,干扰手势逻辑,在touchmove事件中添加阻止默认行为的代码:
modal.addEventListener('touchmove', function handleTouchMove(event) { event.preventDefault(); touchEndX = event.touches[0].clientX; });
4. 修复变量未声明的问题
next.onclick和prev.onclick中的this_img_index未声明,会成为全局变量引发冲突,添加变量声明:
next.onclick = function() { const this_img_index = srcList.indexOf(modalImg.src); // 后续逻辑不变 }
prev.onclick中的this_img_index同理添加const声明。
5. 解决src路径匹配问题
浏览器会将相对路径转为绝对路径存储在modalImg.src中,若srcList存的是相对路径,indexOf会返回-1导致逻辑出错。初始化srcList时统一存储绝对路径,或给图片添加data属性(如data-img-id)作为匹配标识,替代src字符串匹配。
内容的提问来源于stack exchange,提问作者PanosKntz
相关产品推荐
相关产品推荐

