如何通过切换按钮实现图片的平滑过渡效果?
问题描述
我用CSS transition 属性实现了页面元素的平滑切换,其他元素都正常生效,但图片切换部分没法实现平滑过渡。我目前是通过JavaScript修改display属性,切换id为lights-off和lights-on的两张图片的显示状态,相关代码如下:
var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.style.display = "block"; lightsOn.style.display = "none";
切换回来的代码:
var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.style.display = "none"; lightsOn.style.display = "block";
完整代码如下:
JavaScript
function myFunction() { var elements = document.querySelectorAll(".one, .three, .five"); elements.forEach(function(element) { element.classList.toggle("dark-mode"); if (element.classList.contains("dark-mode")) { if (element.classList.contains("one")) { var logoElement = element.querySelector('.logo'); var h2Element = element.querySelector('h2'); var sloganElement = element.querySelector('.slogan'); logoElement.style.setProperty('color', 'white'); sloganElement.style.setProperty('color', 'white'); h2Element.style.setProperty('color', 'white'); } else if (element.classList.contains("three")) { var textThreeOne = element.querySelector('.text-threeone'); var textThreeTwo = element.querySelector('.text-threetwo'); var p = element.querySelector('.text-threetwo + p'); textThreeOne.style.setProperty('color', 'white'); textThreeTwo.style.setProperty('color', 'white'); p.style.setProperty('color', 'white'); var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.style.display = "block"; lightsOn.style.display = "none"; var blackmoon = document.querySelector(".moon"); blackmoon.style.display = "block"; } else if (element.classList.contains("five")) { var inputs = element.querySelectorAll('input'); var textarea = element.querySelector('textarea'); var submitBtn = element.querySelector('input[type="submit"]'); inputs.forEach(input => { input.style.setProperty('background-color', '#1f1f1f'); input.style.setProperty('color', '#ffffff'); }); textarea.style.setProperty('background-color', '#1f1f1f'); textarea.style.setProperty('color', '#ffffff'); submitBtn.style.setProperty('background-color', '#1f1f1f'); // 鼠标悬停颜色 submitBtn.style.setProperty('transition', 'background-color 0.2s'); submitBtn.addEventListener("mouseover", function() { submitBtn.style.setProperty('background-color', '#101010'); }); submitBtn.addEventListener("mouseout", function() { submitBtn.style.setProperty('background-color', '#1f1f1f'); }); var contact = element.querySelector('#contact'); var pOne = element.querySelector('.five>p+p'); var pTwo = element.querySelector('.five>p+p+p'); contact.style.setProperty('color', 'white'); pOne.style.setProperty('color', 'white'); pTwo.style.setProperty('color', 'white'); } else { element.style.setProperty('color', 'white'); } } else { if (element.classList.contains("one")) { var logoElement = element.querySelector('.logo'); logoElement.style.setProperty('color', '#353535'); var sloganElement = element.querySelector('.slogan'); sloganElement.style.setProperty('color', '#353535'); var sloganElement = element.querySelector('h2'); sloganElement.style.setProperty('color', '#353535'); var blackmoon = document.querySelector(".moon"); blackmoon.style.display = "none"; } else if (element.classList.contains("three")) { var textThreeOne = element.querySelector('.text-threeone'); var textThreeTwo = element.querySelector('.text-threetwo'); var p = element.querySelector('.text-threetwo + p'); var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.style.display = "none"; lightsOn.style.display = "block"; p.style.setProperty('color', '#353535'); textThreeOne.style.setProperty('color', '#353535'); textThreeTwo.style.setProperty('color', '#353535'); } else if (element.classList.contains("five")) { var inputs = element.querySelectorAll('input'); var textarea = element.querySelector('textarea'); var submitBtn = element.querySelector('input[type="submit"]'); inputs.forEach(input => { input.style.setProperty('background-color', '#efefef'); input.style.setProperty('color', 'black'); }); textarea.style.setProperty('background-color', '#efefef'); textarea.style.setProperty('color', 'black'); submitBtn.style.setProperty('background-color', '#437bff'); submitBtn.style.setProperty('color', 'white'); // 鼠标悬停颜色 submitBtn.style.setProperty('transition', 'background-color 0.2s'); submitBtn.addEventListener("mouseover", function() { submitBtn.style.setProperty('background-color', '#133edb'); }); submitBtn.addEventListener("mouseout", function() { submitBtn.style.setProperty('background-color', '#437bff'); }); var contact = element.querySelector('#contact'); var pOne = element.querySelector('.five>p+p'); var pTwo = element.querySelector('.five>p+p+p'); contact.style.setProperty('color', '#353535'); pOne.style.setProperty('color', '#353535'); pTwo.style.setProperty('color', '#353535'); } } }); }
CSS
.one, .three, .five { transition: 1500ms; }
HTML
<div> <button class="darkmodebtn" onclick="myFunction()"></button> <img id="lights-off" src="../images/darkmode.png" style="display: none;"> <img id="lights-on" src="../images/ABC.png"> </div>
请问怎么修改才能实现图片的平滑过渡?
解决方案
问题根源是display属性属于离散状态属性,CSS transition无法对其变化生成过渡动画。要实现图片平滑切换,需要改用**透明度(opacity)和可见性(visibility)**属性,配合绝对定位让两张图片重叠,通过类切换控制过渡效果。
步骤1:调整HTML结构与基础CSS
给图片添加容器并设置定位,让两张图片重叠:
<div class="light-container"> <button class="darkmodebtn" onclick="myFunction()"></button> <img id="lights-off" src="../images/darkmode.png" class="light-img"> <img id="lights-on" src="../images/ABC.png" class="light-img active"> </div>
添加对应的CSS规则:
.light-container { position: relative; /* 作为图片的定位容器 */ } .light-img { position: absolute; /* 让两张图片完全重叠 */ top: 0; left: 0; transition: opacity 1.5s ease, visibility 1.5s ease; /* 对透明度和可见性设置过渡 */ visibility: hidden; opacity: 0; } .light-img.active { visibility: visible; /* 激活状态下可见 */ opacity: 1; /* 激活状态下完全不透明 */ } .one, .three, .five { transition: 1500ms; }
步骤2:修改JavaScript逻辑
不再操作display属性,改为切换active类来控制图片显示:
// 深色模式激活时(three元素分支) var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.classList.add('active'); lightsOn.classList.remove('active'); // 深色模式关闭时(three元素分支) var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-on"); lightsOff.classList.remove('active'); lightsOn.classList.add('active');
额外优化建议
- 尽量用CSS类管理状态,避免直接操作元素内联样式——比如把深色模式的文本颜色、输入框样式都写成独立的CSS类,通过
toggle方法切换,代码更简洁易维护。 - 如果两张图片尺寸不同,给
.light-img设置固定宽高,避免切换时出现布局跳动。
内容的提问来源于stack exchange,提问作者andre
相关产品推荐
相关产品推荐

