在 chrome 中更改滤镜时图像在悬停时移动
Image moves on hover when changing filter in chrome
我有一张图片,当我在悬停时模糊它时,它会轻微移动,就像图片在它的位置晃动一样,问题只出现在 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 有关,但 none 的解决方案有效。
更新:
作为, this is a chrome bug and the most stable solution is to wait for it to be fixed. but for now, the best solution for this issue is
我做了很多研究,尝试了很多不同的方法,但似乎没有什么可以解决这个问题。避免这种跳跃的唯一方法是在图像开始时使用模糊效果或删除过渡(因为没有过渡就没有问题,当然这不是要考虑的选项)。
所以我找到的解决方法是使用两个不同的图像并在开始时使用 blur(1px)
。
想法是通过 opacity:0
隐藏具有模糊效果的图像,并使用相同的图像作为背景来模拟初始图像 没有 模糊效果。然后诀窍是使不透明度的过渡比滤镜的过渡更快,这样我们就可以看到 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 代码来执行此操作。您只需创建一个 class 并将其附加到任何需要此效果的图像,然后定位此 class 并为该技巧添加必要的代码。
这是一个例子:
$('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" />
这是最近更新中出现的已确认 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>
我有两个解决方案给你:
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;
}
我发现使它正常工作的唯一方法是使用 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>
我的两分钱:
.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>
我有一张图片,当我在悬停时模糊它时,它会轻微移动,就像图片在它的位置晃动一样,问题只出现在 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 有关,但 none 的解决方案有效。
更新:
作为
我做了很多研究,尝试了很多不同的方法,但似乎没有什么可以解决这个问题。避免这种跳跃的唯一方法是在图像开始时使用模糊效果或删除过渡(因为没有过渡就没有问题,当然这不是要考虑的选项)。
所以我找到的解决方法是使用两个不同的图像并在开始时使用 blur(1px)
。
想法是通过 opacity:0
隐藏具有模糊效果的图像,并使用相同的图像作为背景来模拟初始图像 没有 模糊效果。然后诀窍是使不透明度的过渡比滤镜的过渡更快,这样我们就可以看到 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 代码来执行此操作。您只需创建一个 class 并将其附加到任何需要此效果的图像,然后定位此 class 并为该技巧添加必要的代码。
这是一个例子:
$('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" />
这是最近更新中出现的已确认 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>
我有两个解决方案给你:
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;
}
我发现使它正常工作的唯一方法是使用 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>
我的两分钱:
.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>