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

鼠标悬停/移出缩放切换整改前后图片功能异常,求解决方案

城市环境整改照片切换动画问题解决

需求说明

开发城市环境问题(涂鸦、坑洼等)整改服务的展示功能:

  • 鼠标悬停时显示整改前照片
  • 鼠标移出时恢复显示整改后照片
  • 两次切换均需带有缩放动画

现有代码

index.php

<img alt='<?=$problem->name?>' 
     class='img-fluid' 
     src='uploads/<?=$problem->photoAfter?>' 
     data-before='uploads/<?=$problem->photoBefore?>' 
     data-after='uploads/<?=$problem->photoAfter?>' 
     onMouseOver='hover(this)' onMouseOut='back(this)'>

<script>
    function hover(el){                                
        el.src = el.dataset.before;
        el.classList.remove("after");
        el.classList.add("before");
    }

    function back(el){
        el.src = el.dataset.after;
        el.classList.remove("before");
        el.classList.add("after");     
    }
</script>

site.css

.before {
    animation: scaling 1500ms;    
  }
  
  .after {
    animation: scaling 1500ms;
  }

  @keyframes scaling {
    0% { transform: scale(0); }    
    100% { transform: scale(1);}
  }

当前问题

  1. 鼠标悬停时动画仅生效一次
  2. 悬停时先执行缩放动画,再加载显示整改前图片
  3. 鼠标移出时无动画,直接切换回整改后图片

调整方案

核心思路

用双层图片容器实现切换(避免直接替换src导致的加载延迟和动画不同步),通过CSS transition 控制缩放动画,无需额外JS事件绑定,更稳定可靠。

修改后代码

index.php

<div class="problem-photo-container">
  <!-- 整改前照片:默认缩放隐藏 -->
  <img 
    alt='<?=$problem->name?>(整改前)' 
    class='img-fluid problem-photo problem-photo-before' 
    src='uploads/<?=$problem->photoBefore?>'
  >
  <!-- 整改后照片:默认显示 -->
  <img 
    alt='<?=$problem->name?>(整改后)' 
    class='img-fluid problem-photo problem-photo-after' 
    src='uploads/<?=$problem->photoAfter?>'
  >
</div>

site.css

/* 容器设置相对定位,让两张照片重叠 */
.problem-photo-container {
  position: relative;
  /* 自动适配图片宽度 */
  width: fit-content;
  height: fit-content;
  overflow: hidden;
}

.problem-photo {
  position: absolute;
  top: 0;
  left: 0;
  /* 用transition实现平滑缩放动画,时长可调整 */
  transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 默认状态:整改后照片显示,整改前照片缩小隐藏 */
.problem-photo-after {
  transform: scale(1);
  z-index: 1;
}
.problem-photo-before {
  transform: scale(0);
  z-index: 2;
}

/* 悬停状态:整改后照片缩小隐藏,整改前照片放大显示 */
.problem-photo-container:hover .problem-photo-after {
  transform: scale(0);
}
.problem-photo-container:hover .problem-photo-before {
  transform: scale(1);
}

方案说明

  1. 双层图片布局:两张照片通过绝对定位重叠,避免替换src时的加载延迟,确保动画和图片切换同步。
  2. CSS Transition替代Animation:transition会在元素状态变化时自动触发,解决了原animation仅执行一次的问题,每次悬停/移出都会重新播放动画。
  3. 层级控制:通过z-index确保整改前照片悬停时在最上层,整改后照片默认显示在最上层。
  4. 动画平滑性:使用cubic-bezier曲线可以让动画更自然,时长可根据需求调整(示例中为0.8秒)。

可选优化(若需保留JS逻辑)

如果一定要用单图片切换的方式,需要解决动画触发和图片加载顺序问题:

function hover(el) {
  // 先添加动画类触发缩放缩小
  el.classList.add("scale-out");
  // 等待动画结束后再切换图片
  setTimeout(() => {
    el.src = el.dataset.before;
    // 强制重绘确保动画重新触发
    el.offsetWidth;
    el.classList.remove("scale-out");
    el.classList.add("scale-in");
  }, 800); // 时长和CSS动画一致
}

function back(el) {
  el.classList.add("scale-out");
  setTimeout(() => {
    el.src = el.dataset.after;
    el.offsetWidth;
    el.classList.remove("scale-out");
    el.classList.add("scale-in");
  }, 800);
}

对应的CSS:

.scale-in {
  animation: scale-in 0.8s forwards;
}
.scale-out {
  animation: scale-out 0.8s forwards;
}

@keyframes scale-in {
  from { transform: scale(0); }
  to { transform: scale(1); }
}
@keyframes scale-out {
  from { transform: scale(1); }
  to { transform: scale(0); }
}

但这种方式不如双层图片方案稳定,容易出现加载延迟导致的动画不同步问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:55:53