草庐IT

html - 防止背景图像在 CSS 动画期间调整大小并消除闪烁

coder 2023-08-07 原文

我有一个 <div>我用作幻灯片放映图像容器。将在容器中显示的图像大小不同并作为背景图像应用,而不是 <img>容器内的元素,以便:

  • 我可以根据需要通过媒体查询交换图像集
  • 背景可以动画制作幻灯片效果

  • 我有 background-size:coverbackground-clip:content-box并且这些正确地将图像保持在容器的所需区域内,确保正确剪掉多余的图像。
    第一个问题是在 CSS 动画期间,当一个图像转换到另一个图像时,新图像会在该关键帧的计时过程中调整大小。我想要的是将下一张图像转换为(已经以适当的大小),而不会看到它调整大小。
    实际上,我什至不确定为什么一开始会有交叉淡入淡出可视化,因为我没有这样做的说明(也许是内置的 -webkit- 动画?)。我原以为您会立即看到从一个图像到下一个图像的变化。我实际上喜欢交叉淡入淡出,但不知道它来自哪里让我认为它与调整大小问题有关。
    第二个问题是在幻灯片放映的第一次迭代(仅)期间,图像闪烁并且容器元素的白色背景色被短暂显示。因为这只发生在第一次迭代中,我认为这可能是图像初始下载时间的问题,这就是它在后续迭代中消失的原因。但是,当我在幻灯片放映开始之前添加了一些 JavaScript 来预加载图像并发现相同的问题时,事实证明并非如此。此外,一旦您运行该节目,您的缓存中就会有图像,并且当您刷新页面时(这只会从您的缓存中获取图像,是的,我正在通过从我自己的测试服务器获取文件来进行测试,因此它们将正确缓存)闪烁再次发生。
    我看过一些关于使用 preserve3d 使用各种 CSS 属性设置消除闪烁的帖子。等等,但这些都没有帮助。
    我在 Windows 10 上使用 Chrome 62.0.3202.94 桌面。

    #outerFrame {
      background-color: #22130c;
      box-shadow: inset 0 1px 1px 1px hsla(0,0%,100%,.2), 
                  inset 0 -2px 1px hsla(0,0%,0%,.4), 
                  0 5px 50px hsla(0,0%,0%,.25), 
                  0 20px 20px -15px hsla(0,0%,0%,.2), 
                  0 30px 20px -15px hsla(0,0%,0%,.15), 
                  0 40px 20px -15px hsla(0,0%,0%,.1);
      padding: 1.5em;
      overflow: auto;
      float: left;
      margin: 0 1em 1em 0;
    }
    
    #innerFrame {
      background-color: #fff5e5;
      box-shadow: 0 2px 1px hsla(0,0%,100%,.2), 
                  0 -1px 1px 1px hsla(0,0%,0%,.4), 
                  inset 0 2px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 4px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 6px 3px 1px hsla(0,0%,0%,.1);
      padding: 1.5em;
    }
    
    /* This is the relevant style: */
    #innermostFrame {
      padding: .75em;
      background-color: #fff;
      box-shadow: 0 -1px 0 2px hsla(0, 0%, 0%,.03);
      background-position: 50% 50%;
      background-repeat: no-repeat;
      background-size:cover;  
      background-clip: content-box;
      animation: cycle 8s ease-in-out infinite;
      
      width: 30vw;
      height:40vh;
      min-width: 200px;
      max-width: 900px;
    }
    
    @keyframes cycle {
      0%   { background-image: url("https://picsum.photos/200/300/?random");   }
      25%  { background-image: url("https://picsum.photos/640/480/?random");   }
      50%  { background-image: url("https://picsum.photos/1900/1200/?random"); }
      75%  { background-image: url("https://picsum.photos/480/200/?random");   }
      100% { background-image: url("https://picsum.photos/600/300/?random");   }
    }
    <div id="outerFrame">
      <div id="innerFrame">
        <div id="innermostFrame"></div>
      </div>
    </div>

    我意识到我可以使用其他各种技术(即 JavaScript、堆叠 <img> 元素和管理 opacity 等)来回避这些问题,但我真的想了解导致这两个问题的原因。

    最佳答案

    1. 淡入淡出:

    发生这种情况是因为浏览器试图在关键帧之间设置动画。如果我们查看您的 @keyframes 循环,我们会发现您每 25% 制作一个关键帧。这意味着浏览器将从 0% 到 25% 进行动画处理。它会激活什么?改变的背景。它将如何动画?淡入淡出。此外,背景的大小再次调整以覆盖 div(使用的图片具有不同的格式 - 如果您使用相同的格式 - 这可能不会发生)。

    @keyframes cycle {
      0%   { background-image: url("https://picsum.photos/200/300/?random");   }
      25%  { background-image: url("https://picsum.photos/640/480/?random");   }
      50%  { background-image: url("https://picsum.photos/1900/1200/?random"); }
      75%  { background-image: url("https://picsum.photos/480/200/?random");   }
      100% { background-image: url("https://picsum.photos/600/300/?random");   }
    }
    

    解决方案 A(无淡入淡出和白色背景)

    您可以通过让动画几乎瞬间发生来摆脱调整大小:
    0%   { background-image: url("https://picsum.photos/200/300/?random");   }
    24.99%   { background-image: url("https://picsum.photos/200/300/?random");   }
    25%  { background-image: url("https://picsum.photos/640/480/?random");   }
    

    关键帧 0% 中的背景与关键帧 24.99% 中的背景相同,因此它没有动画。然后它以 25% 的速度变化(这看起来像一个即时的变化)见下面的工作片段:

    #outerFrame {
      background-color: #22130c;
      box-shadow: inset 0 1px 1px 1px hsla(0,0%,100%,.2), 
                  inset 0 -2px 1px hsla(0,0%,0%,.4), 
                  0 5px 50px hsla(0,0%,0%,.25), 
                  0 20px 20px -15px hsla(0,0%,0%,.2), 
                  0 30px 20px -15px hsla(0,0%,0%,.15), 
                  0 40px 20px -15px hsla(0,0%,0%,.1);
      padding: 1.5em;
      overflow: auto;
      float: left;
      margin: 0 1em 1em 0;
    }
    
    
    #innerFrame {
      position: relative;
      background-color: #fff5e5;
      box-shadow: 0 2px 1px hsla(0,0%,100%,.2), 
                  0 -1px 1px 1px hsla(0,0%,0%,.4), 
                  inset 0 2px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 4px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 6px 3px 1px hsla(0,0%,0%,.1);
      padding: 1.5em;
    }
    
    /* This is the relevant style: */
    #innermostFrame{
      padding: .75em;
      background-color: #fff;
      box-shadow: 0 -1px 0 2px hsla(0, 0%, 0%,.03);
      background-position: 50% 50%;
      background-repeat: no-repeat;
      background-size:cover;  
      background-clip: content-box;
      animation: cycle 8s ease-in-out infinite;
      width: 30vw;
      height:40vh;
      min-width: 200px;
      max-width: 900px;
    }
    
    @keyframes cycle {
          0%   { background-image: url("https://picsum.photos/200/300/?random");   }
          24.99%   { background-image: url("https://picsum.photos/200/300/?random");   }
          
          25%  { background-image: url("https://picsum.photos/640/480/?random");   }
          49.99%  { background-image: url("https://picsum.photos/640/480/?random");   }
          
          50%  { background-image: url("https://picsum.photos/1900/1200/?random"); }
          74.99%  { background-image: url("https://picsum.photos/1900/1200/?random"); }
          
          75%  { background-image: url("https://picsum.photos/480/200/?random");   }
          99.99%  { background-image: url("https://picsum.photos/480/200/?random");   }
          
          100% { background-image: url("https://picsum.photos/200/300/?random");    }
    }
    <div id="outerFrame">
      <div id="innerFrame">
        <div id="innermostFrame"></div>
      </div>
    </div>


    注意! 最后一个关键帧 (100%) 应该设置为与第一个 (0%) 相同的值,因为我们希望循环从它停止的地方开始。实际上,这意味着在此示例中您只有 4 个不同的背景图像(如果您想要 5 个 - 取而代之的是 20% 的步长)。

    我们解决了调整背景大小的问题。作为副作用,我们还“修复”了交叉淡入淡出。真正的缺点是动画第一次播放时我们仍然有白色背景。

    2. 白底

    我认为出现白色背景是因为需要先加载图像。它们仅在动画运行时加载。这就是为什么第一次运行低谷有白色背景。

    解决方案 B(带有淡入淡出且无白色背景)

    我们可以使用辅助 div 来恢复交叉淡入淡出效果。但是我们必须在 keframes 中设置不透明度。我们可以在显示另一个 div 的同时在关键帧中设置背景图像 - 这样它就有更多的时间加载并且不会出现白色背景。见下面的片段:

    #outerFrame {
      background-color: #22130c;
      box-shadow: inset 0 1px 1px 1px hsla(0,0%,100%,.2), 
                  inset 0 -2px 1px hsla(0,0%,0%,.4), 
                  0 5px 50px hsla(0,0%,0%,.25), 
                  0 20px 20px -15px hsla(0,0%,0%,.2), 
                  0 30px 20px -15px hsla(0,0%,0%,.15), 
                  0 40px 20px -15px hsla(0,0%,0%,.1);
      padding: 1.5em;
      overflow: auto;
      float: left;
      margin: 0 1em 1em 0;
    }
    
    
    #innerFrame {
      position: relative;
      background-color: #fff5e5;
      box-shadow: 0 2px 1px hsla(0,0%,100%,.2), 
                  0 -1px 1px 1px hsla(0,0%,0%,.4), 
                  inset 0 2px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 4px 3px 1px hsla(0,0%,0%,.2), 
                  inset 0 6px 3px 1px hsla(0,0%,0%,.1);
      padding: 1.5em;
    }
    
    /* This is the relevant style: */
    #innermostFrame,
    #innermostFrame2{
      padding: .75em;
      background-color: #fff;
      box-shadow: 0 -1px 0 2px hsla(0, 0%, 0%,.03);
      background-position: 50% 50%;
      background-repeat: no-repeat;
      background-size:cover;  
      background-clip: content-box;
      animation: cycle 8s ease-in-out infinite;
      width: 30vw;
      height:40vh;
      min-width: 200px;
      max-width: 900px;
    }
    #innermostFrame2{
      position: absolute;
      top: 1.5em; /* padding of innerFrame */
      animation: cycle2 8s infinite;
      background-image: url("https://picsum.photos/200/300/?random"); 
    }
    @keyframes cycle {
      0%   { background-image: url("https://picsum.photos/640/480/?random"); }
      50%  { background-image: url("https://picsum.photos/640/480/?random"); }
      51%  { background-image: url("https://picsum.photos/480/200/?random"); }
      100% { background-image: url("https://picsum.photos/480/200/?random"); }
    }
    @keyframes cycle2 {
      15%  { opacity: 1;}
      25%  { opacity: 0; background-image: url("https://picsum.photos/200/300/?random"); }
      
      26%  { background-image: url("https://picsum.photos/1900/1200/?random");}
      40%  { opacity: 0;}
      50%  { opacity: 1;}
      65%  { opacity: 1;}
      75%  { opacity: 0; background-image: url("https://picsum.photos/1900/1200/?random");}
      
      76%  { background-image: url("https://picsum.photos/200/300/?random");}
      90%  { opacity: 0;}
      100% { opacity: 1;}
    }
    <div id="outerFrame">
      <div id="innerFrame">
        <div id="innermostFrame"></div>
        <div id="innermostFrame2"></div>
      </div>
    </div>


    方案B解释:

    这个想法是让背景图像在显示之前加载。因此有 2 个 div,其中 2 @keyframe动画产生平滑交替的背景。
    #innermostFrame2获得与 #innermostFrame 相同的宽度和高度并且绝对定位(正上方)。 #innermostFrame2的显示和隐藏动画持续时间的 25%。以下是可见的:
             25%                25%               25%                25%
    [ #innermostFrame2 - #innermostFrame - #innermostFrame2 - #innermostFrame ]
    

    百分比:
    #innermostFrame2的背景图片已经设置好了本身 - 使其加载尽可能快。在 @keyframes cycle2不需要 0%,因为背景已经设置并且可见。

    我们希望图像显示 25% 的动画(4 张图像)。现在我决定在这个例子中 10% 的淡入淡出看起来不错(8 秒动画的 10% 是 0.8 秒)。你可以做得更少或更多,因为这是一个品味问题。这就是为什么动画以 15% 的不透明度和 0 25% 的不透明度开始。在 div 不可见之后,我们立即将背景图像更改为 26%,以便可以在 CSS 对象模型中加载它。
    #innermostFrame的背景现在可见(因为 #innermostFrame2 是隐藏的)。我们希望在动画持续时间的 25% 内显示此内容。所以在 50% 我们想要 #innermostFrame2以新背景再次可见。因为我决定在动画持续时间的 10% 内交叉淡入淡出,我们从 opacity: 0; 开始从 40% 开始。 .紧接在 #innermostFrame2 之后完全显示 (50%) 我们改变 #innermostFrame的背景让它加载。这发生在 @keyframes cycle 中的 51%

    关于html - 防止背景图像在 CSS 动画期间调整大小并消除闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47395254/

    有关html - 防止背景图像在 CSS 动画期间调整大小并消除闪烁的更多相关文章

    1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

      我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

    2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

      我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

    3. ruby - capybara field.has_css?匹配器 - 2

      我在MiniTest::Spec和Capybara中使用以下规范:find_field('Email').must_have_css('[autofocus]')检查名为“电子邮件”的字段是否具有autofocus属性。doc说如下:has_css?(path,options={})ChecksifagivenCSSselectorisonthepageorcurrentnode.据我了解,字段“Email”是一个节点,因此调用must_have_css绝对有效!我做错了什么? 最佳答案 通过JonasNicklas得到了答案:No

    4. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

      在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

    5. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

      所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

    6. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

      我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

    7. ruby-on-rails - Ruby url 到 html 链接转换 - 2

      我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

    8. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

      我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

    9. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

      我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

    10. css - 用 watir 检查标签类? - 2

      我有一个div,它根据表单是否正确提交而改变。我想知道是否可以检查类的特定元素?开始元素看起来像这样。如果输入不正确,添加错误类。 最佳答案 试试这个:browser.div(:id=>"myerrortest").class_name更多信息:http://watir.github.com/watir-webdriver/doc/Watir/HTMLElement.html#class_name-instance_method另一种选择是只查看具有您期望的类的div是否存在browser.div((:id=>"myerrortes

    随机推荐