CSS为一个元素连续两次转换

时间:2017-12-18 01:46:57

标签: javascript css vue.js transition

我正在使用VueJS开发棋盘概念。我试图改进人体工程学。

在更换玩家的转弯和观点时,我需要制作一种能够简单掩盖电路板的窗帘:

  • 玩家1只点击目标目标广场
  • 窗帘开始从屏幕的顶部移动到底部(CSS class + transform:translate)
  • 更新游戏模型,并将棋盘显示为播放器2的观点
  • 幕布落下,玩家2现在可以玩了 。等等。

标记看起来像:

<template>
  <div class="board">
    <div class="board-outline">
      <div class="tiles-area" >
        <tile v-for="tile in tiles" v-bind:tile="tile"></tile>
      </div>
    <div class="curtains" 
       v-bind:class="{ 'curtains-out': curtainsOut, 'curtains-in': curtainsIn }">
      <div class="fade-out"></div>
      <div class="opaque"><h1>GET READY !</h1></div>
      <div class="fade-in"></div>
    </div>
  </div>
</template>

游戏状态存储在VueX中,也是窗帘的类(out和in)。电路板尺寸为72vh * 72vh。

如何实现这个?

此致

编辑[并回答]:

正如DecadeMoon向我建议的那样,重写一个完整,简单,独立的例子对我有帮助..

我需要的是

  • 窗帘(init,out,in和reset)的足够状态以正确地产生预期的效果
  • 将定时器从正常状态传递到另一个

这里是代码,问候

 <template>
  <section>
    <div class="board-outline">
      <div class="tiles-area">
        <h1>It's {{ turn }} turn !</h1>
      </div>

      <div class="curtain" v-bind:class="classes">
          <div class="transparent-to-opaque"></div>
          <div class="opaque">
            <h1>GET READY, PLAYER {{turn}} !</h1>
          </div>
            <div class="opaque-to-transparent"></div>
      </div>
    </div>
    <div class="board-aside">
       <h2>simple-curtains-test</h2>
      <p>
        to simulate a real-case curtains fall out and leve in in a turn based game like chess,
        just click the 'source' button first, and then the 'dest' button last
      </p>
      <p>
        <button v-on:click="clickMeFirst">click me first</button>
        <button v-on:click="clickMeSecond">click me second</button>
      </p>
        <p>init : {{ curtain === 'init'  }}</p>                
        <p>out : {{ curtain === 'out' }}</p>
        <p>in : {{ curtain === 'in'  }}</p>        
        <p>reset : {{ curtain === 'reset'    }}</p>                

    </div>
    <br class="clearfix" />
  </section>
</template>

<script>
export default {
  name: 'App',

  data() {
    // in the real app, these will be stored in Vuex modules
    return {
      turn: 'white',
      first: null,
      second: null,
      curtain: 'init'
    }
  },

   computed: {

    classes() {
      return {
        reset: this.curtain == 'reset',
        init:  this.curtain == 'init',
        out:   this.curtain == 'out',
        in:    this.curtain == 'in' 
      }
    }
  },

  methods: {

    clickMeFirst() {
          // setup source board tile
         this.first = 'first'
          this.second = null
        },

        clickMeSecond() {

          // setup dest board tile
          this.second = 'second' 

           if(this.first && this.second) {
            this.curtain = 'out'

            setTimeout(() => {
              if(this.turn === 'black') 
                this.turn = 'white'
              else
                this.turn = 'black'

              this.curtain = 'in'
            }, 500)

        // reset the curtain
       setTimeout(() => { 
         this.curtain = 'reset'
       }, 1000)      

       // reset the curtain
       setTimeout(() => { 
         this.curtain = 'init'
       }, 1500)

      }

     // reset clicked tiles
      this.first = null
      this.second = null        
    }
  }
}
</script>

<style scoped>

* { margin: 0; padding: 0vh;}

section { height:72vh; }

div.board-outline { 
  position: relative;
  float: left;
  height: 72vh;
  width: 72vh; 
  overflow: hidden; 
}

div.board-aside {
  height: 72vh;
  width: 48vh;
  float: left;
  background-color: #ace;
}

div.tiles-area {
  background-color: cyan;
  height: 72vh;
  width: 72vh;
  font-size: 5vh;  
  padding: auto 0;
}

br.clearfix { clear: both; }

div.curtain {
  float: left; 
  position: absolute;
  width: 72vh;
  height: 216vh;

  -webkit-transition: transform 0.5s;
  -moz-transition: transform 0.5s;
  -ms-transition: transform 0.5s;
  -o-transition: transform 0.5s;
  transition: transform 0.5s;

}

div.transparent-to-opaque {
  height: 72vh;
  background: linear-gradient(rgba(0,0,0,0), rgba(0,255,0,255)); 
/*  background-color: black ; */
}

div.opaque {
  height: 72vh;
  background: rgba(0,255,0,255);
}

 div.opaque-to-transparent {
  height: 72vh;
  background: linear-gradient(rgba(0,255,0,255), rgba(0,0,0,0)); 
     /*  background-color: black    ;*/
  }

 /* +72 [init] 0 [out] -72 [in] -144 [reset] -216 */

.init {
  top: 72vh;  
  z-index: -100;
}

.out {
  top: 72vh; 
  transform: translateY(-144vh);
}

.in {
  top: 72vh;   
  transform: translateY(-288vh);
}

.reset {
  top: -216 vh;
  z-index: -100;    
}
</style>

1 个答案:

答案 0 :(得分:0)

有很多方法可以实现这一目标。

我不打算详细介绍您的具体代码,但这里有一个可以帮助您的小例子。

new Vue({
  el: '#app',
  data: {
    player: 'one',
    curtainVisible: false,
  },
  methods: {
    togglePlayer() {
      this.curtainVisible = true;
      setTimeout(() => {
        this.curtainVisible = false;
        this.player = this.player === 'one' ? 'two' : 'one';
      }, 750);
    },
  },
});
#app {
  width: 150px;
  height: 150px;
  margin: 20px auto;
  border: 1px solid #888;
  text-align: center;
  line-height: 150px;
  position: relative;
  overflow: hidden;
  font-size: 20px;
  font-family: sans-serif;
  cursor: pointer;
}

.curtain {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: red;
}

.curtain.v-enter-active,
.curtain.v-leave-active {
  transition: transform 0.5s ease-in-out;
}

.curtain.v-enter,
.curtain.v-leave-to {
  transform: translateY(-100%);
}
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

<div id="app" @click="togglePlayer">
  Player {{ player }}
  
  <transition>
    <div class="curtain" v-show="curtainVisible"></div>
  </transition>
</div>