在vue中给backgroundImage添加过渡效果

add transition effect in vue on backgroundImage

我已经搜索了几天,以便在我通过 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 的原因是因为我正在使用它的网站有一个最容易通过它响应地处理的背景(总是覆盖,不重复并保持居中)。我的第二个问题是,如果没有,是否有可能使其与描述的背景集一起工作 here?

在 codepen 中,我添加了一个 vue guide 的示例,以确保它可以正常工作并且没有其他错误。这个例子非常有效。似乎无法为我的示例找到答案,但我已经开始怀疑这根本不可能,或者我似乎无法找到为什么 vue 没有检测到某些东西正在发生变化。

要使 Vue Transitions 正常工作,您需要更改 DOM 元素。因此,如果您要更改实际图像,这种方法会起作用。在您的示例中,您只是在更改属性值。 DOM 不会触发转换,因为它是同一元素。

但是,您可以使用 :key 属性说服 VUE 替换该元素,从而让您在 2 个元素之间进行过渡。

您也可以像示例中那样使用内联 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>

答案确实是忘记 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 方法一起工作。我希望稍后再研究这个。