使用过渡时的vue模态丢帧

Posted

技术标签:

【中文标题】使用过渡时的vue模态丢帧【英文标题】:vue modal dropping frames when using transitions 【发布时间】:2021-10-07 22:56:29 【问题描述】:

我编写了一个自定义 vue 模态,它在我的电脑上运行良好,但它在某些移动设备上不断丢帧。它似乎与转换有关 - 没有它按预期工作(但看起来和感觉不好)。

在这种情况下,即使是不透明度 1 到不透明度 0 的过渡也会导致延迟。 (任何导致延迟的动画)

这是非常简单的代码,因此它应该适用于所有设备 - 即使是三星 M31 等中端设备也无法毫无延迟地显示动画。 (即使过渡只是不透明度或比例)

菜单.vue

    <Modal :is-open="testModalIsOpen" >
      test1
      test2
      test3
      test4
      test5
    <template #footer>
      <button @click="testModalIsOpen=false">BACK</button>
    </template>
  </Modal>

Modal.vue

<template>
  <transition name="rpg-modal__transition">
    <div class="rpg-modal" v-if="isOpen" :class="classes">
      <div class="rpg-modal__backdrop"></div>
      <div class="mx-auto rpg-modal__content-wrapper">
        <div class="rpg-modal__box" style="background-color: #0b1b3d">
            <div>
              <div class="rpg-modal__body">
                <slot/>
              </div>
              <div class="rpg-modal__footer d-flex justify-content-end">
                <slot name="footer"/>
              </div>
            </div>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
import computed from "@vue/reactivity";

export default 
  name: "Modal",
  props: 
    isOpen: 
      type: Boolean,
      default: false
    ,
    autoPadding: 
      type: Boolean,
      default: true
    
  ,
  setup(props) 
    const classes = computed(() => (
      'rpg-modal--auto-padding': props.autoPadding
    ));

    return 
      classes,
    ;
  

</script>

<style lang="scss">
.rpg-modal 
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  $transition-duration: 0.3s;

  &__transition 
    &-enter-active, &-leave-active 
      transition: all $transition-duration;
    

    &-enter-from, &-leave-to 
      opacity: 0;
      filter: blur(5px);
      transform: scale(1.3);
    
  

  &__backdrop 
    position: absolute;
    height: 100%;
    width: 100%;
    background-color: rgba(0, 0, 0, 0.5);
  

  &__content-wrapper 
    max-width: 64vh;
    margin: auto;
  

  &__box 
    $boxMargin: 13px;
    position: relative;
    margin: $boxMargin;

    max-height: calc(100vh - #$boxMargin * 2);
    border-radius: 15px;

    background-repeat: no-repeat;
    background-size: 100% 100%;

    box-shadow: #00000073 0 0 10px;
  

  &--auto-padding &__body 
    padding: 12px;
  

  &__footer 
    border-top: 1px solid #000000;
    padding: 9px;

    > * 
      margin: .25rem;
    
  

  &__close 
    font-size: 1.5rem;
    line-height: 1;
    text-shadow: 0 1px 0 #fff;

    position: absolute;
    z-index: 20;
    background-color: rgb(62 62 62);
    box-shadow: #00000052 2px 2px 5px;
    color: white;
    height: 30px;
    width: 30px;
    padding: 0 0 4px;
    border-radius: 50px;
    border: none;
    right: 17px;
    top: 17px;
    transition: background-color 200ms;

    &:hover 
      background-color: #9f3e3e;
    
  

</style>

希望任何人都可以提供帮助并感谢任何答案!

【问题讨论】:

我不是移动帧性能方面的专家,但我可能会检查不同动画的测试?如果没有,也许可以使用不同的框架测试相同的组件,看看它是如何执行的。 我尝试了不同的动画。即使是像 opacity 1 到 opacity 0 这样简单的也会导致延迟。但仅在此 Modal 组件中,我无法得到原因。 如果它只在这个 Modal 组件中,那么我会检查是什么导致了这个组件的滞后。或者编写一个新的组件测试动画,也许在你的代码中有一个阶段它正在变慢。实际上我看到了过渡持续时间,请检查您是否正确使用了这些,滞后可能是您添加的过渡持续时间。 模糊滤镜很昂贵 我试过没有模糊滤镜的模态。没有不同。当我不使用任何过渡时,它工作得很好。它只是出现和消失,没有滞后。如果我使用任何过渡(不透明度、变换或模糊......),滞后就会回来 【参考方案1】:

你试过 will-change 属性吗?

CSS 中的 will-change 属性通过让 浏览器知道哪些属性和元素即将成为 操纵,可能会增加该特定的性能 操作。from here

那么,试试这个:

.rpg-modal
  will-change: transform, opacity, filter;

另外,设置modal的初始值,opacity:0等...

【讨论】:

以上是关于使用过渡时的vue模态丢帧的主要内容,如果未能解决你的问题,请参考以下文章

Vue - 过渡

带有 Tailwind css 的 Vue 过渡在淡出时不可见

vue过渡动效

VUE:过渡&动画

vue3动画transition标签使用

如何在材质 ui 上使用过渡使模态居中并使其响应?