首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >移动铬上的动画滞后

移动铬上的动画滞后
EN

Stack Overflow用户
提问于 2021-07-14 21:09:30
回答 5查看 3.2K关注 0票数 5

我在我的网站上做动画。我正在使用类似版本的jsfiddle代码链接如下。当在桌面上观看动画时,效果很好。然而,当在手机上观看,特别是在我的铬浏览器上,有一个奇怪的滞后。当我在手机上打开它时,弹琴显示出完全相同的滞后。如果我重新启动铬应用程序,延迟就会消失,很快就会回来。

这个问题在Safari中没有发生。

我有最新的iPhone与IOS 14.6和铬V90。

https://jsfiddle.net/brodriguez98/e2bvwcja/33/

HTML:

代码语言:javascript
运行
复制
<html>
 <p style = 'margin-top: 100vh;'>above</p>
 
 <img class = 'balltest show-on-scroll standard-push' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
 
 <img class = 'balltest show-on-scroll fade-in' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
  
 <p style = 'margin-bottom: 100vh'>below</p>
</html>

CSS:

代码语言:javascript
运行
复制
.balltest {
    width: 50px;
}

.fade-in {
    opacity: 0;
    -webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
    -moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
    -o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
    transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
    will-change: transform, opacity;
}

.standard-push {
    opacity: 0;
    transform: translateY(4em);
    -webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
    -moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
    -o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
    transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
    will-change: transform, opacity;
}

.is-visible {
    transform: translateY(0);
    opacity: 1;
}

Javascript:

代码语言:javascript
运行
复制
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
    Array.prototype.forEach.call(elementsToShow, function (element) {
        if (isElementInViewport(element)) {
            element.classList.add('is-visible');
        } else {
            element.classList.remove('is-visible');
        }
    });
});


// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
    // special bonus for those using jQuery
    if (typeof jQuery === "function" && el instanceof jQuery) {
        el = el[0];
    }
    var rect = el.getBoundingClientRect();
    return (
        (rect.top <= 0 &&
            rect.bottom >= 0) ||
        (rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
        (rect.top >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
    );
}

我为这个小小的屏幕道歉,我的手机上没有JSfiddle的全屏:

动画在重新启动移动铬后立即工作:https://www.loom.com/share/ac6c843b90d2428bb875572d55e32959

动画中断后不久(当我关闭/重新加载页面):https://www.loom.com/share/e51cf88aa1a74aed8e4d1ed253e83ea0

这正是我在我的网站上看到的使用移动铬浏览器的行为。

更新:下面的答案对我都没有用。我忘了提到这种行为也发生在文本上。此外,谢谢你建议的代码框,我分叉你的代码,并使它更简单,删除图像,但我仍然得到相同的结果,在我的iphone铬浏览器。我还试着用onload函数包装所有东西,但这也不起作用。

目前,我能够用JQuery动画修复这个问题,但我仍然希望CSS3转换能够在我的站点上工作。

https://codesandbox.io/s/animation-test-forked-tqurn?file=/index.html

EN

回答 5

Stack Overflow用户

发布于 2021-07-22 22:20:59

在加载页面时,这看起来像是一个“争用条件”问题。JS在IMG请求完成之前运行。

要理解这个问题,有必要理解加载顺序:

  1. 在加载/重新加载时,服务器使用文档(*.html)文件进行响应
  2. 浏览器开始解析响应(*.html)并为找到的每个资源启动新的请求:
代码语言:javascript
运行
复制
- CSS
- JS
- IMGs
  1. 这些请求按unpredictable顺序完成。例如,大型图像的加载时间可能比*.css文件长,.有些资源可能已经被浏览器缓存并且根本不会启动请求,. 如果对*.js文件的请求在IMGs请求完成之前完成了,则不会为该图像找到呈现的height,并且新添加的CSS类is-visible无论如何都会启动transition .
  2. 一旦IMG请求完成(img被呈现)。为IMG触发一个内容回流。需要重新绘制的元素( IMG)上的正在进行的转换是“重置”,并从keyframe 0开始。这也许能解释你的问题。

以下是三个可能解决问题的选项:

保留图像的最终尺寸。

  • 在CSS中设置一个修复height,并在html中添加类: .myImg {宽度:50;高度:50;}
  • 您还可以添加widthheight作为html属性。即使*.css仍然在加载,最后的维度在JS中也是可用的。

添加一些图像的“负载检测”,防止在图像完全加载之前的过渡。

  • 我们检查img是否已经加载:设置了src,检测到了height -
  • 否则,为该映像设置一个onload事件(因为它尚未加载)
  • 可选:您可以对该映像使用延迟加载,并且只加载“按需”映像(参见最后一个示例)。img的src被设置为data-src属性,并且一旦图像可用,src将由JS设置。

现在,我们可以使用isLoaded(element)函数来排除当前未完全加载的.scroll()中的图像。

这里是jsFiddle,或者展开下面的示例..。

代码语言:javascript
运行
复制
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
    Array.prototype.forEach.call(elementsToShow, function (element) {
        if (isLoaded(element) && isElementInViewport(element)) {
            element.classList.add('is-visible');
        } else {
            element.classList.remove('is-visible');
        }
    });
});

[...elementsToShow].forEach((imgEl, i) => {
    if (
    imgEl.src &&
    imgEl.getBoundingClientRect().height
  ) {
    imgEl.dataset.isLoaded = true;
    console.log(`Img ${i} already loaded`);
  } else {
    console.log(`Img ${i} still loading... or should be lazyloaded`);

    imgEl.onload = function(e) {
      console.log(`Img ${i} finally loaded! onload event`);
        e.target.dataset.isLoaded = true;
        };

    if (imgEl.dataset.src) {
      console.log(`Img ${i} start lazy load...`);
        imgEl.src = imgEl.dataset.src;
    }
  }
})

function isLoaded(el) {
    return el.dataset.isLoaded
}

代码语言:javascript
运行
复制
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
  Array.prototype.forEach.call(elementsToShow, function(element) {
    if (isLoaded(element) && isElementInViewport(element)) {
      element.classList.add('is-visible');
    } else {
      element.classList.remove('is-visible');
    }
  });
});

[...elementsToShow].forEach((imgEl, i) => {
  if (
    imgEl.src &&
    imgEl.getBoundingClientRect().height
  ) {
    imgEl.dataset.isLoaded = true;
    console.log(`Img ${i} already loaded`);
  } else {
    console.log(`Img ${i} still loading... or should be lazyloaded`);
    
    imgEl.onload = function(e) {
      console.log(`Img ${i} finally loaded! onload event`);
      e.target.dataset.isLoaded = true;
    };
    
    if (imgEl.dataset.src) {
      console.log(`Img ${i} start lazy load...`);
      imgEl.src = imgEl.dataset.src;
    }
  }
});

function isLoaded(el) {
  return el.dataset.isLoaded
}

// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
  // special bonus for those using jQuery
  if (typeof jQuery === "function" && el instanceof jQuery) {
    el = el[0];
  }
  var rect = el.getBoundingClientRect();
  return (
    (rect.top <= 0 &&
      rect.bottom >= 0) ||
    (rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
      rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
    (rect.top >= 0 &&
      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
  );
}
代码语言:javascript
运行
复制
.balltest {
  width: 50px;
}

.fade-in {
  opacity: 0;
  -webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
  -moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
  -o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
  transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
  will-change: transform, opacity;
}

.standard-push {
  opacity: 0;
  transform: translateY(4em);
  -webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
  -moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
  -o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
  transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
  will-change: transform, opacity;
}

.is-visible {
  transform: translateY(0);
  opacity: 1;
}
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<p style='margin-top: 100vh;'>above</p>

<img class='balltest show-on-scroll standard-push' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />

<img class='balltest show-on-scroll standard-push' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />

<p style='margin-bottom: 100vh'>below</p>

</html>

C.等待文档的load事件

可以将JS初始化代码包装到整个文档的load事件中。事件在所有重新源(CSS、IMG、..)之后触发。全都装好了。

代码语言:javascript
运行
复制
window.addEventListener('load', (event) => {
    // JS init code hier (images are loaded at this point!)
});
票数 1
EN

Stack Overflow用户

发布于 2021-07-22 22:41:07

我在Chrome浏览器上测试了您的iPhone代码,无法复制显示在屏幕记录中的错误。

这是否与试图在移动铬浏览器上运行整个jsfiddle web应用程序有关?这是一个笨重的web应用程序,除了你正在测试的任何实际输出之外,还会有很多事情发生在引擎盖下面,所以这可能会导致性能问题。最好只测试输出本身。

我已经将您的代码迁移到了一个代码框中,它将允许您在移动浏览器中单独查看输出(参见下面)。您可以自己判断您所看到的问题是否是一个实际的代码错误。

还应该注意到,您正在使用的球图像是文件大小(~200 be )中的相当大,用于显示它的大小。因此,当它在页面上加载时,看到它闪烁是不寻常的。

下面是球映像的较小版本(缩小了80%,并使用https://tinypng.com/进行了优化),最终大小为42 it (您肯定可以使它更小):

--这里是代码框上的相同代码:

https://codesandbox.io/s/animation-test-ok1dp

这里只有输出(尝试在设备上的移动浏览器中查看此内容):

https://ok1dp.csb.app/

这里有一个屏幕视频(我用Chrome浏览器在iPhone上捕捉到):

票数 0
EN

Stack Overflow用户

发布于 2021-07-28 04:01:00

我也面对这种情况。在其他浏览器上,它是平滑的。在Chrome手机上,它是如此的滞后。当我将iPhone更新为iOS 14时,就会出现这种情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68385134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档