在Vue中为背景图片添加过渡效果

3

我已经搜索了几天,想要在通过Vue应用程序更改的背景图像上添加淡入淡出的过渡效果。

这是我一直在测试的代码片段:

new Vue({
  el: "#main",
  data: {
    images: [
      "https://images.freeimages.com/images/large-previews/bfd/clouds-1371838.jpg",
      "https://images.freeimages.com/images/large-previews/ffa/water-lilly-1368676.jpg",
      "https://images.freeimages.com/images/large-previews/efb/lotus-flower-1382251.jpg"
    ],
    current: 0,
    show: false
  },
  methods: {
    changeBG: function () {
      if (this.current < this.images.length - 1) {
        this.current = this.current + 1;
      } else {
        this.current = 0;
      }
    }
  }
});
.main {
  height: 800px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  z-index: 0;
  background-repeat: no-repeat;
  background-size: cover;   
  background-position: center 0px; 
} 
button {
  width: 200px;
  height: 25px;
  margin: 10px; 
}
p.hello{
  color: white;
  margin: 10px;
  font-size: 50px;
}

.fade-enter-active,
.fade-leave-active {
  transition: all 2s linear;
}

.fade-enter-to,
.fade-leave {
  opacity: 0;
}

.fade-enter,
.fade-leave-to {
  opacity: 1;
}

/* hello example transition */
.slide-fade-enter-active {
  transition: all 1s ease;
}
.slide-fade-leave-active {
  transition: all 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter,
.slide-fade-leave-to {
  transform: translateX(10px);
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<transition name="fade">
  <div v-if="changeBG" class="main" id="main" :style="{ backgroundImage: 'url(\'' + images[current] + '\')' }">
    <button v-on:click="changeBG">
      changeBG
    </button>
    <div id="testFromGuide">
      <button @click="show = !show">
        toggleHello
      </button>
      <transition name="slide-fade">
        <p class="hello" v-if="show">all your base are belong to us</p>
      </transition>
    </div>
  </div>
</transition>

我的第一个问题是,这种方法是否可行?我之所以使用backgroundImage是因为我正在使用它的网站有一个最容易通过此方式响应式地处理背景的背景(始终覆盖、不重复并保持居中)。我的第二个问题是,如果不行,是否有可能按照这里所描述的设置背景来使其工作?

在codepen中,我添加了一个vue指南的示例,以确保它可以工作且没有其他错误。这个例子完美地运行。我似乎找不到我的例子的答案,但我开始怀疑它根本就不可能实现,或者我无法找到为什么vue没有检测到某些变化。

2个回答

3
为了让Vue过渡效果起作用,您需要更改DOM元素。因此,如果您要更改实际图像,则此方法将起作用。在您的示例中,您仅更改属性值。由于是相同的元素,DOM不会触发过渡。
然而,您可以使用“:key”属性来说服VUE替换元素,从而在两个元素之间提供过渡效果。
您还可以像在示例中所做的那样使用内联CSS设置图像。您仍然需要在CSS中创建过渡效果。
以下是使用Vue Transition的示例。

new Vue({
  el: "#main",
  data: {
  currentID: 0,
    images: [
'https://images.freeimages.com/images/large-previews/efb/lotus-flower-1382251.jpg',
'https://images.freeimages.com/images/large-previews/ffa/water-lilly-1368676.jpg',
'https://images.freeimages.com/images/large-previews/bfd/clouds-1371838.jpg'
  ]
  },
  methods: {
    toggleImage: function(){
       if(this.currentID < this.images.length-1){
     this.currentID +=1
    } else {
     this.currentID = 0
    }     
    }
  }
});
body {
  overflow: hidden;
}

.main {
  position: relative;
}

img {
  width: 100%;
  height: auto;
  display: block;
  position: absolute;
  -webkit-transition: all 3s ease;
  transition: all 3s ease;
}

button {
  z-index: 100;
  position: relative;
  width: 200px;
  height: 25px;
  margin: 20px;
}

/* prefix with transition name */
.slide-fade-enter-active {
  opacity: 1;
  z-index: 10;
}

.slide-fade-leave-active {
  opacity: 1;
}

.slide-fade-enter,
.slide-fade-leave-to {
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div class="main" id="main">
    <transition name="slide-fade">
<!--    SRC comes from the array of images the :key is important for vue to believe its a 'new' DOM element and do the transition -->
      <img v-bind:src="images[currentID]" v-bind:key="currentID" />
    </transition>
 <button @click="toggleImage">
      Toggle Image
    </button>
</div>

然而,由于它使用图像标签,您无法对此进行很多控制。相反,最好使用背景图像,如下所示:

new Vue({
  el: "#main",
  data: {
  currentID: 0,
    images: [
'https://images.freeimages.com/images/large-previews/efb/lotus-flower-1382251.jpg',
'https://images.freeimages.com/images/large-previews/ffa/water-lilly-1368676.jpg',
'https://images.freeimages.com/images/large-previews/bfd/clouds-1371838.jpg'
  ]
  },
  methods: {
    toggleImage: function(){
       if(this.currentID < this.images.length-1){
     this.currentID +=1
    } else {
     this.currentID = 0
    }     
    }
  }
});
.main {
  /* make this the size of the window */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.theImage {
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: #333;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center center;
  -webkit-transition: all 3s ease;
  transition: all 3s ease;
}

button {
  z-index: 100;
  position: relative;
  width: 200px;
  height: 25px;
  margin: 20px;
}

/* prefix with transition name */
.slide-fade-enter-active {
  opacity: 1;
  z-index: 10;
}

.slide-fade-leave-active {
  opacity: 1;
}

.slide-fade-enter,
.slide-fade-leave-to {
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div class="main" id="main">
    <transition name="slide-fade">
<!--    SRC comes from the array of images the :key is important for vue to believe its a 'new' DOM element and do the transition -->
   <div class="theImage" v-bind:style="{'background-image': 'url(' + images[currentID] + ')'}" v-bind:key="currentID"></div>
    </transition>
 <button @click="toggleImage">
      Toggle Image
    </button>
</div>


这个回答对于像我这样的业余爱好者来说非常晦涩难懂,但它让我找到了一种行之有效的解决方案。 - Stijn Van der Linden
抱歉我没有时间制作一个例子。看起来你找到了一个解决方案,但如果需要的话,我很乐意添加一个例子。 - Bryce Howitson
1
你有点走了弯路。我会建立一个示例并编辑我的答案。你可能想使用 div 而不是 img,因为这样你会得到更多的 CSS 控制。 - Bryce Howitson
1
这里有一个使用Vue中响应式数据属性获取过渡效果的示例。基本上,你只需要替换一个属性并设置:key值,让Vue执行过渡即可。 - Bryce Howitson
1
是的,您可以重复使用过渡效果。请确保图像或 div 获得了 z-index,其中新的更高,并确保所有转换元素都具有唯一键。 - Bryce Howitson
显示剩余5条评论

0
答案确实是忘记Vue过渡,让CSS来完成工作。可以在这里找到一个可行的示例:

new Vue({
  el: "#main",
  data: {
    show: false,
    BG1: true,
    BG2: false,
    BG3: false
  },
  methods: {
    changeBG: function(){
     if (this.BG1 == true){
    this.BG1 = false;
    this.BG2 = true;
        this.BG3 = false;
   } else if (this.BG2 == true) {
    this.BG1 = false;
    this.BG2 = false;
        this.BG3 = true;
   } else if (this.BG3 == true) {
    this.BG1 = true;
    this.BG2 = false;
        this.BG3 = false;
   }       
    },
    showBG1: function(){
   if (this.BG1 == true){
    return "";
   } else {
    return "transparent";
   }
    },
    showBG2: function(){
   if (this.BG2 == true){
    return "";
   } else {
    return "transparent";
   }
    },
    showBG3: function(){
   if (this.BG3 == true){
    return "";
   } else {
    return "transparent";
   }
    }    
  }
});
.main {
} 

#bgs img.transparent {
  opacity:0;
  transform: translateY(-0.0px);
}

#bgs img{
  /* Set rules to fill background */
  min-height: 100%;
  min-width: 1024px;
 
  /* Set up proportionate scaling */
  width: 100%;
  height: auto;
 
  /* Set up positioning */
  position: fixed;
  top: 0;
  left: 0;
  
  z-index: -1;
  -webkit-transition: all 0.5s ease-in-out;
  -moz-transition: all 0.5s ease-in-out;
  -o-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;    
}

@media screen and (max-width: 1024px) { /* Specific to this particular image */
  #bgs img{
    left: 50%;
    margin-left: -512px;   /* 50% */
  }
}

button {
  z-index: 100;
  position: relative;
  width: 200px;
  height: 25px;
  margin: 20px; 
}
p.hello{
  color: white;
  margin: 40px;
  font-size: 50px;
}

.fade-enter-active {
  transition: all 1s ease;
}
.fade-leave-active {
  transition: all 1s ease;
}
.fade-enter, .fade-leave-to{
  transform: translateY(-5px);
  opacity: 0;
}

/* hello example transition */
.slide-fade-enter-active {
  transition: all 1s ease;
}
.slide-fade-leave-active {
  transition: all 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter,
.slide-fade-leave-to {
  transform: translateY(-5px);
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div class="main" id="main">
  <div id="bgs">
    <img :class="showBG1()" src="https://images.freeimages.com/images/large-previews/efb/lotus-flower-1382251.jpg">
    <img :class="showBG2()" src="https://images.freeimages.com/images/large-previews/ffa/water-lilly-1368676.jpg">
   <img :class="showBG3()" src="https://images.freeimages.com/images/large-previews/bfd/clouds-1371838.jpg">
  </div>
  <button @click="changeBG">
    changeBG
  </button>
  <div id="testFromGuide">
    <button @click="show = !show">
      toggleHello
    </button>
    <transition name="slide-fade">
      <p class="hello" v-if="show">all your base are belong to us</p>
    </transition>
  </div>
</div>

目前还不完美,因为每添加一个额外的背景,我都需要添加一个函数并在changeBG函数中添加一个额外的if else循环。如果可以使用列表变量来完成这个任务,那将更加优雅,但我还没有找到一种方法来使其与:class方法兼容。我希望以后能够研究这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接