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

如何用原生JavaScript实现CSS裁剪蒙版的向下动画效果

嘿,我来帮你搞定这个clip-path的平滑动画问题!首先得说下你当前代码里的小问题:你用style.clip去修改裁剪效果,但实际CSS里用的是clip-path(包括-webkit-前缀),这俩是不同的属性,得操作正确的那个才行。另外直接修改属性值不会有动画,因为clip-path的变化默认没有过渡效果,下面给你两种纯原生JS的实现方案,都不用jQuery~


方案1:CSS过渡+自定义属性(简洁省心)

这种方法利用CSS的transition自动处理动画,只需要用JS修改自定义属性的值就行,代码量少还流畅:

第一步:修改你的CSS

给#duotonetop添加过渡效果,并用自定义属性定义裁剪区域的上下值:

#duotonetop {
  padding: 0;
  /* 用自定义属性存裁剪的上下百分比 */
  --clip-top: 0%;
  --clip-bottom: 90%;
  -webkit-clip-path: inset(var(--clip-top) 0 var(--clip-bottom) 0);
  clip-path: inset(var(--clip-top) 0 var(--clip-bottom) 0);
  /* 添加过渡动画,时长可以自己调,这里设为1秒 */
  transition: -webkit-clip-path 1s ease, clip-path 1s ease;
  height: auto;
  position: fixed;
  display: block;
  transform: translateY(-500px);
}

第二步:更新JS函数

现在只要修改自定义属性的值,过渡动画就会自动生效:

function bottomClip() {
  const el = document.getElementById("duotonetop");
  el.style.setProperty('--clip-top', '90%');
  el.style.setProperty('--clip-bottom', '0%');
}

function reClip() {
  const el = document.getElementById("duotonetop");
  el.style.setProperty('--clip-top', '0%');
  el.style.setProperty('--clip-bottom', '90%');
}

点击图片的时候,裁剪蒙版就会平滑地从顶部滑到底部啦~


方案2:用requestAnimationFrame手动控帧(更灵活)

如果你想精细控制动画的节奏、缓动曲线,就用原生JS的requestAnimationFrame逐帧更新裁剪值:

替换你的JS函数

// 通用动画函数:控制clip-path从起始值过渡到目标值
function animateClipPath(el, startTop, endTop, startBottom, endBottom, duration) {
  const startTime = performance.now();
  
  function updateFrame(currentTime) {
    const elapsed = currentTime - startTime;
    // 计算动画进度(0到1)
    let progress = Math.min(elapsed / duration, 1);
    
    // 可选:换成ease-in-out缓动曲线,动画更自然
    progress = progress < 0.5 
      ? 2 * progress * progress 
      : 1 - Math.pow(-2 * progress + 2, 2) / 2;
    
    // 计算当前帧的裁剪值
    const currentTop = startTop + (endTop - startTop) * progress;
    const currentBottom = startBottom + (endBottom - startBottom) * progress;
    
    // 设置裁剪属性
    el.style.webkitClipPath = `inset(${currentTop}% 0 ${currentBottom}% 0)`;
    el.style.clipPath = `inset(${currentTop}% 0 ${currentBottom}% 0)`;
    
    // 没完成的话继续下一帧
    if (progress < 1) {
      requestAnimationFrame(updateFrame);
    }
  }
  
  requestAnimationFrame(updateFrame);
}

// 触发向下动画
function bottomClip() {
  const el = document.getElementById("duotonetop");
  // 从top=0%/bottom=90% 动画到 top=90%/bottom=0%,时长1000ms
  animateClipPath(el, 0, 90, 90, 0, 1000);
}

// 还原初始状态
function reClip() {
  const el = document.getElementById("duotonetop");
  animateClipPath(el, 90, 0, 0, 90, 1000);
}

这个方案可以随意调整动画时长、缓动效果,适合需要定制化动画的场景。


完整代码示例(用方案1)

CSS(style.css)

@font-face { font-family: Fraktur; src: url(typefaces/BreitkopfFraktur.ttf); } 
@font-face { font-family: Noe; src: url(typefaces/noe.ttf); } 

html { 
  background-image: url(images/hero.jpg); 
  overflow-x: hidden; 
  overflow-y: auto; 
} 

body { 
  text-align: center; 
  overflow: hidden; 
  margin: 0 !important; 
  padding: 0 !important; 
} 

h1 { 
  font-family: Fraktur; 
  margin-top: 15%; 
  color: white; 
  font-size: 12em; 
  display: inline; 
} 

#duotonetop { 
  padding: 0;
  --clip-top: 0%;
  --clip-bottom: 90%;
  -webkit-clip-path: inset(var(--clip-top) 0 var(--clip-bottom) 0);
  clip-path: inset(var(--clip-top) 0 var(--clip-bottom) 0);
  transition: -webkit-clip-path 1s ease, clip-path 1s ease;
  height: auto; 
  position: fixed; 
  display: block; 
  transform: translateY(-500px); 
} 

.cont { margin-top: 15%; }

HTML

<!DOCTYPE html> 
<html> 
<head> 
  <link rel="stylesheet" href="css/style.css"> 
</head> 
<body> 
  <center> 
    <div class="cont"> 
      <span class="js-animate" data-speed="2" data-position="top" style="transform: translate3d(0px, 0px, 0px);"> 
        <h1>a</h1> 
      </span> 
      <h1>m</h1> 
      <h1>s</h1> 
      <h1>t</h1> 
      <h1>e</h1> 
      <h1>r</h1> 
      <h1>d</h1> 
      <h1>a</h1> 
      <h1>m</h1> 
    </div> 
  </center> 
  <a onclick="bottomClip()"><img id="duotonetop" src="css/images/hero_duotone.png"></a> 
  <script> 
    function bottomClip() {
      const el = document.getElementById("duotonetop");
      el.style.setProperty('--clip-top', '90%');
      el.style.setProperty('--clip-bottom', '0%');
    }

    function reClip() {
      const el = document.getElementById("duotonetop");
      el.style.setProperty('--clip-top', '0%');
      el.style.setProperty('--clip-bottom', '90%');
    }
  </script> 
</body> 
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:41:22