【问题标题】:Image moves on hover when changing filter in chrome更改 chrome 中的过滤器时图像在悬停时移动
【发布时间】:2018-06-03 12:46:35
【问题描述】:

我有一个图像,当我在悬停时模糊它,它会轻微移动,就像图像在它的位置上晃动,问题只发生在 chrome 中(测试:chromium 63 linux-x86_64),

.item img{
  transition: 250ms all ease-in-out;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.item:hover img{
  filter: blur(2px)
}

我认为它可能与 this issue 有关,但没有一个解决方案有效。

更新:

作为@Chase said,这是一个chrome错误,最稳定的解决方案是等待它修复。但目前,这个问题的最佳解决方案是@kosh Very's answer

【问题讨论】:

  • 您是否尝试将transform: translateZ(0); 添加到您的.item img {} 中? jsfiddle.net/oto7quwL
  • @AndyHoffman 是的,我有,即使在你的小提琴中,图像也会移动!
  • 这个似乎终于在v73中修复了。

标签: css google-chrome css-transitions css-filters


【解决方案1】:

我做了很多研究,尝试了很多不同的方法,但似乎没有任何东西可以解决这个故障。避免这种跳转的唯一方法是在图像的开头添加模糊效果或移除过渡(因为没有过渡就没有问题,当然这不是一个可以考虑的选项)。

所以我发现的解决方法是使用两个不同的图像并在开头使用blur(1px)

想法是让带有模糊效果的图像被opacity:0 隐藏,并使用相同的图像作为背景来模拟初始图像没有模糊效果。那么诀窍就是让 opacity 的过渡比滤镜的过渡快,这样我们就可以看到blur(1px) 的效果,然后是blur(2px) 的效果

.item {
  width: 200px;
  height: 150px;
  background: url(https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg);
  background-size: 100%;
}

img {
  width: 200px;
  display: inline-block;
  transition: 2s filter ease-in-out, 0.1s opacity ease-in-out;
  filter: blur(1px);
  opacity: 0;
}

img:hover {
  opacity: 1;
  filter: blur(2px);
}
<div class="item">
  <img src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
</div>

我认为这个技巧涉及更多的 HTML/CSS,并且您必须更改站点上的每个图像,但是您可以例如创建一个 jQuery 代码来执行此操作。您只需创建一个附加到任何需要此效果的图像的类,然后定位该类并添加该技巧的必要代码。

这是一个例子:

$('img.blur').each(function() {
  var url = $(this).attr('src');
  $(this).wrap("<div style='display:inline-block;font-size:0;background-image:url(" + url + ");background-size: 100%;'></div>")
})
.blur {
  transition: 2s filter ease-in-out, 0.1s opacity ease-in-out;
  filter: blur(1px);
  opacity: 0;
}

.blur:hover {
  opacity: 1;
  filter: blur(3px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<img src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" width="200" class="blur">

<img src="https://lorempixel.com/300/300/" width="300" class="blur" />

<img src="https://lorempixel.com/400/400/" width="400" class="blur" />

【讨论】:

    【解决方案2】:

    这是一个已确认的 Chrome 错误,在最近的更新中出现,希望很快得到解决。

    这是一个简化的测试用例:https://codepen.io/chasebank/pen/KZgYXK

    这是标记为待分类的Chromium issue

    我认为目前最好的做法是什么都不做。等待实施适当的修复。破解确认浏览器错误绝不是一个好主意。

    我们可以放心,看到此消息的其他人只有 最近更新的 Chrome 用户。我的第一次尝试是询问一个充满熟练开发人员的 Slack 频道,甚至 他们 都没有看到。

    $('#toggleBlur').click(function() {
      $('#content').toggleClass('blur')
    })
    body {
      padding: 5%;
    }
    
    div {
      filter: blur(0px);
    }
    
    .blur {
      filter: blur(.1px)
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="toggleBlur">Toggle blur</button>
    
    <div id="content">
      <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Accusantium eum nisi voluptate eaque! Sequi sit nemo iste. Earum accusantium rerum consectetur cumque sequi maiores maxime reiciendis, alias beatae accusamus labore.</p>
      <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Voluptate enim magnam nemo atque, ad placeat ab unde consequatur minima velit, ipsam tempora laudantium molestias sapiente perspiciatis quaerat modi ratione voluptatem?</p>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Deleniti commodi cum sed nemo fugiat non esse ex quos consectetur ipsam alias laboriosam, cumque eaque omnis quae accusamus, repellat dolore modi!</p>
    </div>

    【讨论】:

    • 我现在仍然有这个错误,过滤器:亮度变换:translate3d(0,0,0) 似乎正在修复它,虽然我没有像素完美的眼睛。我应该在某处报告吗?
    【解决方案3】:

    我有两个解决方案:

    filter:blur(0.2px) hack(don't ask me how it works)

    .item img
    {
      transition: filter 250ms ease-in-out;
      filter: blur(0.2px); /* the lowest value I could get on my machine: 0.12805650383234025436px */
      image-rendering: -webkit-optimize-contrast; /* just in case quality degrades */
    }
    
    .item:hover img
    {
      filter: blur(2px);
    }
    

    除了笑话,这可能是由处理单元完成的浮点数优化引起的,所以通过将模糊设置为 .2px,我不是在为模糊(0px)设置动画,而是从另一个值开始,而不是像这样计算它(假设我们有线性缓动):

    frame1: 0, frame2: .1, frame3: .2, frame4: .3, ...

    它是这样计算的:

    frame1: .2, frame2: .2666, frame3: .3332, ...

    所以增量值已经改变,不再导致错误定位。当然这里没有适当的数学运算(这对于缓动特别棘手),但你明白了。

    这也会通过抖动跳过第一帧。



    Duplicate blurred image and toggle between them(也是最高效的方式)

    <div class="item">
        <img class="blurred"  src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
        <img class="original" src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
    </div>
    

    .item
    {
      position: relative;
    }
    
    .item img
    {
      max-width: 300px;
      transition: opacity 250ms ease-in-out;
      will-change: opacity;
    }
    
    .item .original
    {
      transition-delay: 0;
    }
    
    .item .blurred
    {
      position: absolute;
      filter: blur(5px);
      opacity: 0;
      transition-delay: .1s;
    }
    
    .item:hover .original
    {
      opacity: 0;
      transition-delay: .2s;
    }
    .item:hover .blurred
    {
      opacity: 1;
      transition-delay: .1s;
    }
    

    【讨论】:

    • 我不得不把它推到 blur(.3px) 但那是唯一对我有用的东西
    • 过滤器:模糊(2px);为我工作,花了我一个小时......
    【解决方案4】:

    我发现使这项工作正常工作的唯一方法是使用 svg 滤镜并使用 GSAP 为滤镜模糊设置动画。

    https://jsfiddle.net/eg5yhu26/4/

    var timeline = TweenMax.to("#hue1feGaussianBlur", 5, {
      paused: true,
      attr: {
        "stdDeviation": 5
      },
      onUpdateParams: ["{self}"]
    });
    
    $(document).on("mouseenter", ".c-grid__item a", function() {
      timeline.play();
    });
    $(document).on("mouseleave", ".c-grid__item a", function() {
      timeline.reverse();
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.14.2/TweenMax.min.js"></script>
    <div class="c-grid">
      <div class="c-grid__item">
        <a href="" title="">
          <svg width="100%" height="100%" viewBox="0 0 538 196" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <defs>Using feColorMatrix for Tint FX</defs>
            <!--<filter id="hue1">
            <feColorMatrix id="hue1feColorMatrix" in="SourceGraphic" type="hueRotate" values="0"/>
     </filter>-->
            <filter id="hue1" x="0" y="0">
              <feGaussianBlur id="hue1feGaussianBlur" in="SourceGraphic" stdDeviation="0" />
            </filter>
            <image xlink:href="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" width="100%" height="100%" filter="url(#hue1)" />
          </svg>
        </a>
      </div>
    </div>

    【讨论】:

      【解决方案5】:

      我的两分钱:

      .item {
        width: 200px;
        height: 150px;
        overflow:hidden;
      }
      
      img {
        width: 200px;
        transition:filter .5s;
        
        transform: translate3d(-1px, -1px, 0);
        border:solid 1px transparent;
        border-width:1px 0 0 1px;
      }
      
      img:hover {
        filter: blur(5px);
      }
      <div class="item">
        <img src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
      </div>

      【讨论】:

      • 完美,谢谢,我已经进一步减少了代码,它仍然有效。看到这支笔:codepen.io/DEfusion/pen/VQPGvx
      • @DEfusion,感谢您的评论!你是对的,overflowtransform 可以做到这一点,但 border 是必要的,以补偿 transform 的偏移以达到像素完美。虽然在某些情况下可能会被省略。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 2018-07-20
      • 2023-01-11
      相关资源
      最近更新 更多